How to secure the ASP.NET_SessionId cookie?

Solution 1:

To add the ; secure suffix to the Set-Cookie http header I simply used the <httpCookies> element in the web.config:

<system.web>
  <httpCookies httpOnlyCookies="true" requireSSL="true" />
</system.web>

IMHO much more handy than writing code as in the article of Anubhav Goyal.

See: http://msdn.microsoft.com/en-us/library/ms228262(v=vs.100).aspx

Solution 2:

Here is a code snippet taken from a blog article written by Anubhav Goyal:

// this code will mark the forms authentication cookie and the
// session cookie as Secure.
if (Response.Cookies.Count > 0)
{
    foreach (string s in Response.Cookies.AllKeys)
    {
        if (s == FormsAuthentication.FormsCookieName || "asp.net_sessionid".Equals(s, StringComparison.InvariantCultureIgnoreCase))
        {
             Response.Cookies[s].Secure = true;
        }
    }
}

Adding this to the EndRequest event handler in the global.asax should make this happen for all page calls.

Note: An edit was proposed to add a break; statement inside a successful "secure" assignment. I've rejected this edit based on the idea that it would only allow 1 of the cookies to be forced to secure and the second would be ignored. It is not inconceivable to add a counter or some other metric to determine that both have been secured and to break at that point.

Solution 3:

Going with Marcel's solution above to secure Forms Authentication cookie you should also update "authentication" config element to use SSL

<authentication mode="Forms">
   <forms ...  requireSSL="true" />
</authentication>

Other wise authentication cookie will not be https

See: http://msdn.microsoft.com/en-us/library/vstudio/1d3t3c61(v=vs.100).aspx

Solution 4:

Found that setting the secure property in Session_Start is sufficient, as recommended in MSDN blog "Securing Session ID: ASP/ASP.NET" with some augmentation.

    protected void Session_Start(Object sender, EventArgs e)
    {
        SessionStateSection sessionState = 
 (SessionStateSection)ConfigurationManager.GetSection("system.web/sessionState");
        string sidCookieName = sessionState.CookieName;

        if (Request.Cookies[sidCookieName] != null)
        {
            HttpCookie sidCookie = Response.Cookies[sidCookieName];
            sidCookie.Value = Session.SessionID;
            sidCookie.HttpOnly = true;
            sidCookie.Secure = true;
            sidCookie.Path = "/";
        }
    }

Solution 5:

Adding onto @JoelEtherton's solution to fix a newly found security vulnerability. This vulnerability happens if users request HTTP and are redirected to HTTPS, but the sessionid cookie is set as secure on the first request to HTTP. That is now a security vulnerability, according to McAfee Secure.

This code will only secure cookies if request is using HTTPS. It will expire the sessionid cookie, if not HTTPS.

    // this code will mark the forms authentication cookie and the
    // session cookie as Secure.
    if (Request.IsSecureConnection)
    {
        if (Response.Cookies.Count > 0)
        {
            foreach (string s in Response.Cookies.AllKeys)
            {
                if (s == FormsAuthentication.FormsCookieName || s.ToLower() == "asp.net_sessionid")
                {
                    Response.Cookies[s].Secure = true;
                }
            }
        }
    }
    else
    {
        //if not secure, then don't set session cookie
        Response.Cookies["asp.net_sessionid"].Value = string.Empty;
        Response.Cookies["asp.net_sessionid"].Expires = new DateTime(2018, 01, 01);
    }