Wednesday, December 29, 2010

How to secure Classic ASP Session ID with Pure ASP

    This is the second part of my first blog "

How to secure Classic ASP Session ID (ASPSESSIONID) with JAVASCRIPT"

In this blog, I'll demonstrate how to achieve the same goal with only Classic ASP without the help of client side javascript.

Step 1: Login page (login.asp).
<html>
<head>
<script type="text/javascript">        
        alert(document.cookie);
</script>
</head>
<body>
<%
    Dim cookies
    cookies = Request.ServerVariables("HTTP_COOKIE")
%>
Server Cookies:<%= cookies %>;
<form name="login" onsubmit="" action="session2.asp">
<input type="text" name="username" />
<input type="text" name="password" />
<input type="hidden" name="sessionid" value="" />
<input type="submit" value="Login" />
</form>
</body>
</html>
This is the login page and you will see the ASPSESSIONID in both javascript alert and the html page. Redirect to another page for authentication.

Step 2: Authentication page (session2.asp).

<%
    'CODE for authorization/authentication
    '...
    'get ASPSESSIONID
    Dim aspsessionid
    aspsessionid = Request.ServerVariables("HTTP_COOKIE")
    aspsessionid = "ASPSESSIONID" & Split(Split(aspsessionid,"ASPSESSIONID")(1),"=")(0)
    'if login successful
    'delete the current session id to generate new one
    Response.AddHeader "Set-Cookie",aspsessionid & "=0"
    'redirect to another page to get new session id
    Response.Redirect "Session3.asp"
%>

If login is successful, current session id will be read and assign invalid value to it. That will force the web server to generate new session id. Then redirect to new page to get new session id.

Step 3: Reading new session key (session3.asp)
<%
    'redirect to another page to get new session id
    Response.Redirect "Session4.asp"
%>
In this page, current browser session id value will be "0" and server generate new session id. Redirect to next page again to get newly generated session id.

Step 4: Privileged page (session4.asp).
<%
    'get ASPSESSION cookie
    Dim AspSessionCookie
    AspSessionCookie = Request.ServerVariables("HTTP_COOKIE")
    AspSessionCookie = "ASPSESSIONID" & Split(AspSessionCookie,"ASPSESSIONID")(1)
    if  InStr(1,AspSessionCookie,";") then
        AspSessionCookie = Split(AspSessionCookie,";")(0)        
    end if
    Response.AddHeader "Set-Cookie", AspSessionCookie & ";secure;httponly"
%>

<html xmlns="http://www.w3.org/1999/xhtml" >
<head>
    <script type="text/javascript">        
        alert(document.cookie);
    </script>
</head>
<body onload="">
<%= AspSessionCookie %>
    ASP Session ID has been secured. :)
    <a href="session5.asp">visit</a>
</body>
</html>
In this page, both session key and value will be read and append "httponly" and "secure" flags to it. Then append those values to the response header.
Now you will not be able to access ASPSESSIONID via client side javascript and unsecurely.

We are done!

:)

Thursday, December 23, 2010

How to secure Classic ASP Session ID with JAVASCRIPT

     To secure our websites, we need to secure our session ID. Although there are solutions for Asp.net and other programming languages, there isn't any solution for classic asp. 
     There is not any built-in features in classic asp to achieve that. So I have to invent my own way to secure it based on the available language's features and by adding some tweaks.
     First of all, to secure the asp session ID, we need to change session ID after authentication and set two flags to asp session cookie, httponly and secure flags. Unfortunately, classic asp's session ID is read-only and we cannot set it directly from vbscript. And asp session ID is generated randomly, we need some tweaks to get both key and the value. Here are the steps:
  1. Read current asp session id's key at login page.
  2. When user login request is sent to authentication page, send this session key.
  3. If the user is authorized, set invalid value to current session id and that will force the web server to generate new session id. 
  4. Redirect the page to new page to get a new session id.
  5. Read new session id's key and value
  6. Send new session id to new page
  7. Add httponly and secure flag to new session id.

Step 1: Login page (login.asp).
<html>
<head>
<script type="text/javascript">
        function getSessionKey()
        {
        var c_name = "ASPSESSIONID";
        if (document.cookie.length>0)
          {
          c_start=document.cookie.indexOf(c_name);
          if (c_start!=-1)
            {
            c_end=document.cookie.indexOf("=",c_start);
            if (c_end==-1) c_end=document.cookie.length;
            return unescape(document.cookie.substring(c_start,c_end));
            }
          }
        return "";
        }
        
        function submit()
        {
            document.login.sessionid.value = getSessionKey();
        }
</script>
</head>
<body onload="submit()">
<form name="login" onsubmit="" action="authenticate.asp">
<input type="text" name="username" />
<input type="text" name="password" />
<input type="hidden" name="sessionid" value="" />
<input type="submit" value="Login" />
</form>
</body>
</html>
Here current session id will be read and will store it in the hidden field. When the form is submitted, this hidden value will also be sent.

Step 2: Authentication page (authenticate.asp).

<%
    'CODE for authorization/authentication
    '...
    
    'if login successful
    'delete the current session id to generate new one
    Response.AddHeader "Set-Cookie", Request("SessionID") & "=0"
    'redirect to another page to get new session id
    Response.Redirect "NewSession.asp"
%>

Here current session id will be read from the request's form field. Set invalid value to it and redirect to another page. When setting invalid value to Session ID, the web server will re-generate new session ID and will send it to the browser in subsequent response.

Step 3: Reading new session key (NewSession.asp)
<html>
<head>
<script type="text/javascript">
        
        function getCookie()
        {
         var c_name = "ASPSESSIONID";
         var cok;
        if (document.cookie.length>0)
          {
          c_start=document.cookie.indexOf(c_name);
          if (c_start!=-1)
            {
            //c_start=c_start + c_name.length+1;
            c_end=document.cookie.indexOf(";",c_start);
            if (c_end==-1)
            { 
                c_end=document.cookie.length;
                cok = unescape(document.cookie.substring(c_start,c_end) + ';');
            }
            else
            {
                cok = unescape(document.cookie.substring(c_start,c_end));
            }
            return cok;
            }
          }
        return "";
        }
        
        function submit()
        {
            document.login.sessionid.value = getCookie();
            document.login.submit();
        }
</script>
</head>
<body onload="submit()">
<form name="login" onsubmit="" action="UserAccount.asp">
<input type="hidden" name="sessionid" value="" />
</form>
</body>
</html>
Here new session id will be read from cookie and assign it to the hidden field. When the form is submitted, this hidden value will also be sent. In the next page, this new session ID will be retrieved and set two flags.


Step 4: Privileged page (UserAccount.asp).
<%
    Response.AddHeader "Set-Cookie", Request("SessionID") & "secure;httponly"
%>

<html xmlns="http://www.w3.org/1999/xhtml" >
<head>
    <script type="text/javascript">        
        alert(document.cookie);
    </script>
</head>
<body onload="">
    ASP Session ID has been secured. :)
    <a href="session5.asp">visit</a>
</body>
</html>
Here current session id will be read from the request and append "secure" and "httponly" flags to them. By adding these two flags, session ID will only be sent to the client when using secure channel and session ID will no longer be accessible from client side javascript. This will prevent XSS (cross site scripting).

We are done!

:)