Forum Discussion
How to properly insert HttpOnly and Secure cookie directives?
There are countless posts on this topic on devcentral. I'm sure that most of the proposed solutions worked fine for the contributors specific situations. We've been using one of the earliest solutions (the one that uses switch -glob to set Secure and HttpOnly attributes), since 2009. It satisfied our security department's requirements and served it's purpose, but it always bothered me that if either attribute was already set, we ended up with cookies that contained duplicate HttpOnly and/or Secure attributes.
During our migration from version 9.4.8 to new hardware running 11.4.1, I discovered that this problem still existed. F5 support referenced bug 343455 and pointed me to this forum for a solution. They recommended that we change our application to set cookies with a lower-case expires attribute, or change it to lower case using an iRule. I have no idea how long the bug has been open, or when a fix will be available. It bothers me a bit that support pointed me back to the first place that I looked to for a solution.
At any rate, thank you all for your suggestions. I'm hoping that support has a clear handle on the problem, but I don't know if that's the case. I haven't seen an official SOL document or clear definition of the problem and suggested work around. After considerable testing, I came to the following conclusions:
1) HTTP::cookie parsing is flawed at best. It works fine in some circumstances, but the presence of an unrecognized cookie attribute ( like Expires in v11.4.1, or HttpOnly in 9.4.8) causes HTTP:cookie names to return an invalid list. In our case, a java application was setting the following cookie: PERSID=""; Expires=Thu, 01-Jan-1970 00:00:10 GMT;
HTTP::cookie functions reported that we had 3 cookies named PERSID, 01-Jan-1970 and GMT. This might have something to do with the value of the Expires attribute containing embedded spaces and not being enclosed in quotes (which the specification doesn't require).
2) Even the solution that we've been using since 2009 has one basic flaw. It incorrectly assumes that HTTP::cookie value returns the value from the Set-Cookie header (including attributes).
3) Attempts to use version 11 specific functions ( HTTP::cookie httponly enable ) resulted in illegal argument exceptions being thrown by the iRule. Attempts to change the version of the cookie resulted in the same exception. I suspect that those functions would work if we deleted the original cookie before trying to set those values.
4) Changing the Expires attribute to lower-case does work, but I can't be sure that it won't cause problems with some browsers, or ASM security policies for that matter.
5) At this point, I'm choosing to avoid use of HTTP::cookie functions for now. With a few modifications to our existing iRule and suggestions from the above posts, I came up with the following iRule.
It's working well so far and eliminates the presence of duplicate HttpOnly and Secure attributes on cookies that already have them.
when HTTP_RESPONSE priority 100 {
if { [catch { set setckval [HTTP::header values "Set-Cookie"]
HTTP::header remove "Set-Cookie"
foreach value $setckval {
if { "" != $value } {
set testvalue [string tolower $value]
set valuelen [string length $value]
switch -glob $testvalue {
"*;secure*" -
"*; secure*" { }
default { set value "$value; Secure"; }
}
switch -glob $testvalue {
"*;httponly*" -
"*; httponly*" { }
default { set value "$value; HttpOnly"; }
}
HTTP::header insert "Set-Cookie" $value
F5 support recommended that we change the Expires attribute to lower-case
When this is done, HTTP::cookie functions appear to work correctly.
Cookie specifications rfc2109, rfc2165 and rfc6265 all show attribute
names starting with an upper-case letter, but specifies that browsers
must treat them as case-insensitive. If you want to change the expires
attribute to lower-case, the following statement can be used instead of
the header insert statement above.
HTTP::header insert "Set-Cookie" [string map {Expires expires} $value]
log local0. "client=[IP::client_addr] server=[IP::remote_addr] cookie=$value"
}
}
} ] } {
log local0. "Exception thrown, client_addr=[client_addr] HttpOnly and/or Secure cookie attributes may not have been set"
}
}
Help guide the future of your DevCentral Community!
What tools do you use to collaborate? (1min - anonymous)Recent Discussions
Related Content
* Getting Started on DevCentral
* Community Guidelines
* Community Terms of Use / EULA
* Community Ranking Explained
* Community Resources
* Contact the DevCentral Team
* Update MFA on account.f5.com
