How to add Httponly and Secure attributes to HTTP cookies (for 11.5.x)

Problem this snippet solves:

Problem this snippet solves:

The script adds Httponly and Secure attributes to cookies issued by the server.

In v12.x software there is a better way to achieve the same outcome with using HTTP::cookie commands (even though adding Httponly requires additional tweaks because of the issue with cookie version field see discussion here). However, in v11.5 and earlier releases HTTP::cookie commands do not work as expected (in particular, upper case chracters cookie attributes e.g. "Expire" and "GMT" are parsed with errors, as discussed in 19-Oct-2013 post by DanW here). Furthermore, in these software versions F5 Persistent Cookies do not have "Httponly" attributes and adding them using HTTP::cookie command appears to be impossible (as "HTTP::cookie version" command cannot be used for F5-generated cookies).

Note: the HTTP::cookie commands repairs non-RFC-compliant attributes "httponly=<any text>" and "secure=<any text>" by replacing them with "Httponly" and "Secure" respectively. The script below does not perform such replacements and leaves these non-RFC-compliant attributes unmodified (without adding duplicates of the attributes). We consider fixing non-RFC-compliant syntax to be out of the scope. Browsers we tested ignored the <any text> values (in "httponly=<any text>" and "secure=<any text>" attributes).

How to use this snippet:

How to use this snippet:

The same instance of this iRule can be applied to a mixture of HTTP or HTTPS Virtual Servers and will automatically disable insertion of “Secure” attribute for the HTTP VSs.

Tested on Versions: 11.5.2 HF1; 11.5.4 HF2; 12.1.1 HF1

Code :

when CLIENT_ACCEPTED {
set httpsVs [PROFILE::exists clientssl]
# to determine whether the connection is via an HTTP or HTTPS VS
# it can be done with [SSL::cert count] and catch in HTTP_RESPONSE
# event, but there would have been a bigger perfomance impact 
}
when HTTP_RESPONSE {
   set setckval [HTTP::header values "Set-Cookie"]
   HTTP::header remove "Set-Cookie"
   # this command removes all cookies from the responce, so we have to remove and then 
   # re-insert in any case (rather then do it selectively on an as-needed per-cookie basis)
   foreach cookie1 $setckval {
set cookie1 [string trimright [string trimright $cookie1] ";"]
# to avoid obtaining multiple semicolons (e.g. ";;Secure" or "; ;Secure") in the output
# if the orginal cookie had a trailing semicolon, possibly, followed by spaces
# trailing semicolons, strictly saying, do not meet rules described in RFC 2965 
# but there are reports of applications using them (e.g. Cisco Bug: CSCso95114)
set list1 [lrange [split $cookie1 ";"] 1 end]
# the first field (cookie name=value pair) is skipped to ensure that even cookies
# that happen to have names "httponly" or "secure" are processed properly
set hasHttpOnly false
if { $httpsVs } { set hasSecure false}
else { set hasSecure true }  
#i.e. insertion of "Secure" is disabled for non-HTTPS VSs
foreach item1 $list1 {
   set titem1 [string tolower [string trim $item1]]
   # accordring to RFC 2965 leading and trailing WSP characters in atrributes 
   # should be ignored and attributes should be treated as case-insensitive;
   if { ($titem1 eq "httponly") or  ($titem1 starts_with "httponly=") } {
set hasHttpOnly true
   }
   if { ($titem1 eq "secure") or ($titem1 starts_with "secure=")} {
set hasSecure true
   }
}
if { not $hasHttpOnly } {
set cookie1 "${cookie1}; Httponly"
#log local0. "Missing Httponly attribute is being added to cookie: $cookie1"
}
if { not $hasSecure } {
set cookie1 "${cookie1}; Secure"
#log local0. "Missing Secure attribute is being added to cookie: $cookie1"
}
#log local0. "The following cookie is being rewritten: $cookie1"
HTTP::header insert "Set-Cookie" $cookie1
   }
}
Published Dec 08, 2016
Version 1.0

Was this article helpful?

8 Comments

  • I am running BIG Version 11.6.1 without any hotfix, I am trying to apply these with above mentioned IRule but I do not see any secure cookies or httponly in response header ( Using Fiddler )

     

    Please suggest me or help me how to fix it this. Thanks for your help !!!

     

    Regards, Eswar

     

  • I am running BIG Version 11.6.1 without any hotfix, I am trying to apply these with above mentioned IRule but I do not see any secure cookies or httponly in response header ( Using Fiddler )

     

    Please suggest me or help me how to fix it this. Thanks for your help !!!

     

    Regards, Eswar

     

  • VadimT's avatar
    VadimT
    Icon for Nimbostratus rankNimbostratus

    Hi Eswar, It is possible that your browser still uses old cookies, so the server does not need to send updated ones. I would start with removing all cookies for the VS/FQDN in question from your browser cache. Then I would access the VS via browser and after that I would check the list of (updated) cookies to see whether the "httponly" (and "secure" for HTTPS) attributes are there. Fiddler can be used for this second step, but you still would need to start with clearing the cookies. Please let me know how it went. I have not tested the iRule with 11.6.x software, but it should work.

     

  • VadimT's avatar
    VadimT
    Icon for Nimbostratus rankNimbostratus

    Sorry... I forgot to add. In Chrome to clear individual cookies and then check their content you would need to got to: Settings (advanced) -> Privacy -> Content Settings -> All cookies and site data

     

  • when HTTP_RESPONSE { set setckval [HTTP::header values "Set-Cookie"] HTTP::header remove "Set-Cookie" foreach cookie1 $setckval { set cookie1 [string trimright [string trimright $cookie1] ";"] set list1 [lrange [split $cookie1 ";"] 1 end] set hasHttpOnly false if { $httpsVs } { set hasSecure false} else { set hasSecure true } foreach item1 $list1 { set titem1 [string tolower [string trim $item1]] if { ($titem1 eq "httponly") or ($titem1 starts_with "httponly=") } { set hasHttpOnly true } if { ($titem1 eq "secure") or ($titem1 starts_with "secure=")} { set hasSecure true } } if { not $hasHttpOnly } { set cookie1 "${cookie1}; Httponly" } if { not $hasSecure } { set cookie1 "${cookie1}; Secure" } HTTP::header insert "Set-Cookie" $cookie1 } }

     

  • when HTTP_RESPONSE { set setckval [HTTP::header values "Set-Cookie"] HTTP::header remove "Set-Cookie" foreach cookie1 $setckval { set cookie1 [string trimright [string trimright $cookie1] ";"] set list1 [lrange [split $cookie1 ";"] 1 end] set hasHttpOnly false if { $httpsVs } { set hasSecure false} else { set hasSecure true } foreach item1 $list1 { set titem1 [string tolower [string trim $item1]] if { ($titem1 eq "httponly") or ($titem1 starts_with "httponly=") } { set hasHttpOnly true } if { ($titem1 eq "secure") or ($titem1 starts_with "secure=")} { set hasSecure true } } if { not $hasHttpOnly } { set cookie1 "${cookie1}; Httponly" } if { not $hasSecure } { set cookie1 "${cookie1}; Secure" } HTTP::header insert "Set-Cookie" $cookie1 } }

     

  • In version 12 you don't need an irule, because the cookie profile has HTTPOnly and Secure flag options.