32

Does anyone know exactly how to set HTTPONLY on classic ASP session cookies?

This is the final thing that's been flagged in a vulnerability scan and needs fixing ASAP, so any help is appreciated.

~~~A LITTLE MORE INFORMATION ON MY PROBLEM~~~

Can anyone please help me with this?

I need to know how to set HTTPONLY on the ASPSESSION cookie created by default from ASP & IIS.

This is the cookie automatically created by the server for all asp pages.

If needed i can set HTTPONLY on all cookie across the site.

Any help on how to do this would be massively appreciated.

Thanks

Thanks Elliott

AnthonyWJones
  • 178,910
  • 32
  • 227
  • 302
E.Shafii
  • 321
  • 1
  • 3
  • 4

7 Answers7

14

Microsoft includes an example using an ISAPI filter to all outbound cookies: http://msdn.microsoft.com/en-us/library/ms972826

or URL rewriting could be used http://forums.iis.net/p/1168473/1946312.aspx

<rewrite>
        <outboundRules>
            <rule name="Add HttpOnly" preCondition="No HttpOnly">
                <match serverVariable="RESPONSE_Set_Cookie" pattern=".*" negate="false" />
                <action type="Rewrite" value="{R:0}; HttpOnly" />
                <conditions>
                </conditions>
            </rule>
            <preConditions>
                <preCondition name="No HttpOnly">
                    <add input="{RESPONSE_Set_Cookie}" pattern="." />
                    <add input="{RESPONSE_Set_Cookie}" pattern="; HttpOnly" negate="true" />
                </preCondition>
            </preConditions>
        </outboundRules>
    </rewrite>
sep15ms
  • 839
  • 1
  • 8
  • 6
  • 9
    While this works - I have to advise that if any of your Classic ASP pages have Response.Buffer=false , the page will be pure garbage. – Jason Oct 18 '11 at 20:56
  • Anyone having issues to implement this code, you must first enable URL Rewrite for IIS [ http://www.iis.net/downloads/microsoft/url-rewrite ] – MarceloBarbosa May 07 '15 at 21:27
  • For me, the HTTP flag in dev tools is set to true, but then after a second, the flag will be removed. Does this have something to do with using HTTPS? – Coded Container Sep 26 '17 at 17:44
  • URL Rewrite for IIS sadly doesn't work in a cluster :-( – Matt Deemer Sep 04 '19 at 12:10
3

If you have IIS7 + you need to make sure the URL Rewrite module is installed. You can install it with the Web Platform Installer. The Web Platform Installer can be found in the features view for your website. You need to run IIS Manager as administrator.

Run IIS As Administratro

Click on the Web Platform Installer in the features view for your website:

Web Platform Installer

Maker sure the URL Rewrite Server Product is installed. If it isn't, then install it.

Url Rewrite Server Product

With the URL Rewrite Server Product installed, you can use the URL Rewrite Feature on your website to add a rule to add HttpOnly for your Session ID cookies.

URL Rewrite Feature

enter image description here

Add HttpOnly Outbound Rule

You should see, if it doesn't already exist, a web.config file created for your ASP site. it will have the following contents:

enter image description here

If you use Firebug in Firefox to inspect your cookies, you should now see the HttpOnly flag set:

enter image description here

Jeremy Ray Brown
  • 1,183
  • 12
  • 20
  • 1
    Well explained..Great job!! – VPP Sep 08 '15 at 14:53
  • 3
    Lovely explanation. I would add the following details. You need to create a Precondition. When doing so, name it "No HttpOnly". Using "Regular Expressions", Local grouping "Match All". Add two conditions. First, {RESPONSE_SET_COOKIE}, Matches the Pattern, "." (without the quotes). Second, {RESPONSE_SET_COOKIE}, Does Not Match the Pattern, "; No HttpOnly" (without the quotes). – Mark Goldfain Jul 16 '18 at 20:46
1
Response.AddHeader "Set-Cookie", "CookieName=CookieValue; path=/; HttpOnly" 

Source: http://www.asp101.com/tips/index.asp?id=160

Martin Eve
  • 2,525
  • 1
  • 20
  • 23
  • 5
    Because this cookie is created by ASP & IIS by default we don't have the opportunity programmatically to add this. I'm wondering if it's some other setting somewhere else??? I updated the KeepASPCookieSecure in the IIS Metabase.xml, i'm wondering if this might be a similar kind of fix?? – E.Shafii Jun 07 '10 at 15:58
  • 1
    Please note that adding the cookie using "addheader" will -not- add the cookie to the request.cookies() collection in ASP in the same request. The cookie will only be visible in the request.cookies scope after a browser-roundtrip. This differs from the regular response.cookies() command, which will make the cookie available in the request.cookies scope within the same request. – Erik Oosterwaal Sep 27 '16 at 08:07
1

I compiled the Microsoft's ISAPI filter example. This solved my problem.

The ISAPI DLL is here

Feel free to download.

0

Setting the ASP session cookie as HttpOnly can be done in web.config using URLrewrite:

<rewrite>
    <outboundRules>
        <rule name="Secure ASP session cookie">
            <match serverVariable="RESPONSE_Set_Cookie" pattern="ASPSESSIONID(.*)" negate="false" />
            <!--<action type="Rewrite" value="ASPSESSIONID{R:1}; HttpOnly; Secure" />-->
            <action type="Rewrite" value="ASPSESSIONID{R:1}; HttpOnly" />
        </rule> 
    </outboundRules>
</rewrite>

It's also possible to use URLrewrite to make all cookies HttpOnly / Secure, but sometimes you need cookies to be readable in JavaScript, so here's a collection of functions and sub routines I wrote a while ago for creating regular cookies that can enable or disable "HttpOnly" and "Secure":

' *********************************************************************************************************
' Set a cookie
' *********************************************************************************************************

sub set_cookie(cookie_name,cookie_value,cookie_path,http_only,secure,expire)

    Dim cookie_header, split_expire, expire_value

    ' Set the cookie name and value. The value must be URL encoded.

    cookie_header = cookie_name & "=" & server.URLEncode(cookie_value) & "; "

    ' To set cookies that can be accessed by sub domains, you need to specify the domain as
    ' ".mydomain.com". If no domain is specified then the cookie will be set as "host only",
    ' and only be accessible to the domain it was set on. Un-comment to disable host only:

    'cookie_header = cookie_header & "Domain=.mydomain.com; "

    ' Check the expire value for a specific expiry length (e.g; "1 year")
    ' For session cookies, the expiry should be set to null.

    if NOT isDate(expire) AND NOT isNull(expire) then

        ' Remove any double spaces and trim the value.

        expire = replace(expire,"  "," ")
        expire = trim(expire)

        ' Split on space to separate the expiry value from the expiry unit.

        split_expire = split(expire," ")

        ' A uBound value of 1 is expected

        if uBound(split_expire) = 1 then

            expire_value = split_expire(0)
            if NOT isNumeric(expire_value) then exit sub
            expire_value = int(expire_value)

            select case lCase(split_expire(1))

                case "minute","minutes"
                    expire = DateAdd("n",expire_value,Now())
                case "hour","hours"
                    expire = DateAdd("h",expire_value,Now())
                case "day","days"
                    expire = DateAdd("d",expire_value,Now())
                case "week","weeks"
                    expire = DateAdd("ww",expire_value,Now())
                case "month","months"
                    expire = DateAdd("m",expire_value,Now())
                case "year","years"
                    expire = DateAdd("yyyy",expire_value,Now())
                case else
                    ' unknown expiry unit, exit sub
                    exit sub
            end select

        else

            ' Unexpected uBound. This means no space was included when specifying the expiry length
            ' or multiple spaces were included. 

            exit sub

        end if

    end if

    ' Set the expiry date if there is one. If the expiry value is null then no expiry date will be set and 
    ' the cookie will expire when the session does (a session cookie).

    ' The expiry date can only be UTC or GMT. Be sure to check your servers timezone and adjust accordingly.

    if isDate(expire) then

        ' The cookie date needs to be formatted as:
        ' WeekDayName(shortened), day-monthName(shortened)-year timestamp(00:00:00) GMT/UTC

        expire = cDate(expire)
        cookie_header = cookie_header & "expires=" &_ 
        weekday_name(WeekDay(expire),true) & ", " &_ 
        ZeroPad(Day(expire)) & "-" &_ 
        month_name(Month(expire),true) & "-" &_ 
        year(expire) & " " &_ 
        timeFromDate(expire) & " UTC; "

    end if

    cookie_header = cookie_header & "path=" & cookie_path & "; "

    ' HttpOnly means cookies can only be read over a HTTP (or HTTPS) connection.
    ' This prevents JavaScript from being able to read any cookies set as HttpOnly.
    ' HttpOnly should always be used unless you're setting a cookie that needs to
    ' be accessed by JavaScript (a CSRF token cookie for example).

    if http_only then
        cookie_header = cookie_header & "HttpOnly; "
    end if

    ' A "secure" cookie means the cookie can only be accessed over a HTTPS connection.
    ' If we try to create a secure cookie over a none HTTPS connection it will be 
    ' rejected by most browsers. So check the HTTPS protocol is ON before setting a
    ' cookie as secure. This check is particularly useful when running on a localhost,
    ' most localhosts don't use HTTPS, so trying to set a Secure cookie won't work. 

    if secure AND uCase(request.ServerVariables("HTTPS")) = "ON" then
        cookie_header = cookie_header & "Secure; "
    end if          

    ' Add the header and remove the trailing ";"

    response.AddHeader "Set-Cookie",left(cookie_header,len(cookie_header)-2)

end sub


' *********************************************************************************************************
' Delete a cookie   
' *********************************************************************************************************

sub delete_cookie(cookie_name)

    ' There is no header for deleting cookies. Instead, cookies are modified to a date that
    ' has already expired and the users browser will delete the expired cookie for us.

    response.AddHeader "Set-Cookie",cookie_name & "=; " &_
    "expires=Thu, 01-Jan-1970 00:00:00 UTC; path=/"

end sub


' *********************************************************************************************************
' When the LCID is set to 1033 (us) vbLongTime formats in 12hr with AM / PM, this is invalid for a cookie
' timestamp. Instead, we use vbShortTime which returns the hour and minute as 24hr with any LCID, then use
' vbLongTime to get the seconds, and join the two together.
' *********************************************************************************************************

function timeFromDate(ByVal theDate)
    Dim ts_secs : ts_secs = split(FormatDateTime(theDate,vbLongTime),":")       
    if uBound(ts_secs) = 2 then
        timeFromDate = FormatDateTime(theDate,vbShortTime) & ":" & left(ts_secs(2),2)
    else
        timeFromDate = "00:00:00"   
    end if
end function


' *********************************************************************************************************
' WeekDayName and MonthName will return a value in the native language based on the LCID.
' These are custom functions used to return the weekday and month names in english, 
' reguardless of the LCID
' *********************************************************************************************************

function weekday_name(weekday_val, shorten)

    select case weekday_val

        case 1
            if shorten then weekday_name = "Sun" else weekday_name = "Sunday"
        case 2
            if shorten then weekday_name = "Mon" else weekday_name = "Monday"
        case 3
            if shorten then weekday_name = "Tue" else weekday_name = "Tuesday"
        case 4
            if shorten then weekday_name = "Wed" else weekday_name = "Wednesday"
        case 5
            if shorten then weekday_name = "Thu" else weekday_name = "Thursday"
        case 6
            if shorten then weekday_name = "Fri" else weekday_name = "Friday"
        case 7
            if shorten then weekday_name = "Sat" else weekday_name = "Saturday"

    end select

end function

function month_name(month_val, shorten)

    select case month_val

        case 1
            if shorten then month_name = "Jan" else month_name = "January"
        case 2
            if shorten then month_name = "Feb" else month_name = "February"
        case 3
            if shorten then month_name = "Mar" else month_name = "March"
        case 4
            if shorten then month_name = "Apr" else month_name = "April"
        case 5
            month_name = "May"
        case 6
            if shorten then month_name = "Jun" else month_name = "June"
        case 7
            if shorten then month_name = "Jul" else month_name = "July"
        case 8
            if shorten then month_name = "Aug" else month_name = "August"
        case 9
            if shorten then month_name = "Sep" else month_name = "September"
        case 10
            if shorten then month_name = "Oct" else month_name = "October"
        case 11
            if shorten then month_name = "Nov" else month_name = "November"
        case 12
            if shorten then month_name = "Dec" else month_name = "December"

    end select

end function


' *********************************************************************************************************
' Prefix a 1 digit number with a 0. Used in date formatting
' *********************************************************************************************************

function zeroPad(theNum)
    if len(theNum) = 1 then
        zeroPad = cStr("0" & theNum)
    else
        zeroPad = theNum
    end if
end function

Examples:

' **************************************************************************************************************
' set_cookie(COOKIE NAME, COOKIE VALUE, COOKIE PATH, HTTPONLY (BOOLEAN), SECURE (BOOLEAN), EXPIRY DATE / LENGTH)
' **************************************************************************************************************

' Expire on a specific date: 

call set_cookie("cookie_name1","cookie value","/",true,true,"15 Jan 2019 12:12:12")
call set_cookie("cookie_name2","cookie value","/",true,true,"15 January 2019 12:12:12")

call set_cookie("cookie_name3","cookie value","/",true,true,"Jan 15 2019 12:12:12")
call set_cookie("cookie_name4","cookie value","/",true,true,"January 15 2019 12:12:12")

call set_cookie("cookie_name5","cookie value","/",true,true,"Jan 15 2019")
call set_cookie("cookie_name6","cookie value","/",true,true,"January 15 2019")

' Expire when the session ends (a sesson cookie):

call set_cookie("cookie_name7","cookie value","/",true,true,null)

' Specify an expiry length:

call set_cookie("cookie_name8","cookie value","/",true,true,"20 minutes")
call set_cookie("cookie_name9","cookie value","/",true,true,"1 hour")
call set_cookie("cookie_name10","cookie value","/",true,true,"10 days")
call set_cookie("cookie_name11","cookie value","/",true,true,"3 weeks")
call set_cookie("cookie_name12","cookie value","/",true,true,"1 year")

' Delete a cookie:

call delete_cookie("cookie_name")

' This would also work for deleting a cookie:

call set_cookie("cookie_name","","/",false,false,"-1 year")
Adam
  • 959
  • 1
  • 6
  • 10
0

old but good, add this in a globally included asp :

Dim AspSessionCookie
AspSessionCookie = Request.ServerVariables("HTTP_COOKIE")

If instr(AspSessionCookie,"ASPSESSIONID") > 0 Then
    AspSessionCookie = "ASPSESSIONID" & Split(AspSessionCookie,"ASPSESSIONID")(1)
    If  InStr(1,AspSessionCookie,";") then
        AspSessionCookie = Split(AspSessionCookie,";")(0)        
    End If

    Response.AddHeader "Set-Cookie", AspSessionCookie & ";HttpOnly"
End If
edestrero
  • 486
  • 6
  • 5
-1

This page has lots of information that's relevant to your problem.

.NET 1.1 doesn't add HttpOnly because it hadn't been invented yet.

If your app will run under .NET 2.0 (I moved several Classic ASP sites to 2.0 virtually unchanged) HttpOnly is set by default.

If I read him right, you can get the Session cookie and append ; HttpOnly; to it. He gives a java example:

String sessionid = request.getSession().getId();
response.setHeader("SET-COOKIE", "JSESSIONID=" + sessionid + "; HttpOnly");

Lastly, he suggests:

if code changes are infeasible, web application firewalls can be used to add HttpOnly to session cookies

Edited to add: to those who think migrating to .NET (which can accommodate most Classic ASP code unchanged) is too drastic a change to get such a small feature, my experience of ISAPI filters is that they, too, can be a major pain, and in some common situations (shared hosting) you can't use them at all.

egrunin
  • 23,366
  • 5
  • 44
  • 92
  • 7
    Sorry if your downvotes were not clear but changing your entire site from classic ASP to .NET seems a fairly major undertaking just to get HttpOnly session cookies. I think that is the reason for the downvotes. – mike nelson Mar 09 '11 at 02:23