Increased Security With First Party Cookies
HTTP cookies are an essential part of many web based applications, useful for tracking session and state information. But they can also be exploited to leak information to third party sites using a method known as Cross Site Request Forgery (CSRF). A CSRF attack takes advantage of the web browser behavior which results in cookies being sent to third party sites when a page contains mixed content. This results in cross-site information leakage, and depending on the content of the cookies, could provide an attacker with information to hijack a user session.
SameSite Attribute
As of this writing, there is a Internet draft standard for directing clients to only send ‘first party’ cookies. In a nutshell, the standard defines a new, backwards-compatible attribute for the Set-Cookie header named SameSite. When the SameSite attribute is present, compliant browsers will only send that cookie with requests where the requested resource and the top-level browsing context match the cookie. This becomes another layer of a “defense in depth” strategy, mitigating CSRF and cross-site script including (XSSI) attacks. SameSite is supported in recent Chrome and Firefox browsers.
SameSite can be specified alone, or with explicit values “Strict” or “Lax”, corresponding to differing levels of lock-down.
Specifying SameSite can increase security, but it is not appropriate for all applications. One example would be “mash-up” applications, those which intentionally pull and embed content from different sites, may require cross-site cookies to function correctly. Also, some single sign-on features may require cross-context authentication that involves cookies.
So how can you secure your apps? Big IP provides 3 ways to add SameSite attribute to Set-Cookie headers, two of which are described below: iRules and LTM Policy. Mentioned in another article, the Application Security module also provides a setting to enable SameSite.
iRule to add SameSite attribute
Here is iRule which can handle multiple Set-Cookie headers in a response. If a Set-Cookie header already has SameSite attribute present, it is passed through unmodified. This allows an administrator to set a baseline security level, say by specifying “SameSite=Lax” in an iRule, but allows for individual apps to control their security level by generating headers with their own Set-Cookie header, with say “SameSite=Strict”.
when HTTP_RESPONSE { # Set-Cookie header can occur multiple times, treat as list set num [HTTP::header count Set-Cookie] if {$num > 0} { foreach set_cookie [HTTP::header values Set-Cookie] { # only modify if header does not have SameSite attribute set foundSameSite [string match -nocase "*SameSite*" $set_cookie ] if {[expr {!$foundSameSite} ]} { set set_cookie [concat $set_cookie "; SameSite"] } # collect modified and unmodified values in list newcookies lappend newcookies $set_cookie } if {$num == 1} { # overwrite existing HTTP::header Set-Cookie [lindex $newcookies 0] } else { # remove and replace HTTP::header remove Set-Cookie foreach set_cookie $newcookies { HTTP::header insert Set-Cookie $set_cookie } } } }
LTM Policy
Below is a sample LTM Policy which will tag “; SameSite” to the end of a Set-Cookie header that doesn’t have one already. One limitation to be aware of is that there can be multiple Set-Cookie headers in an HTTP response, and LTM policy can only replace the last one.
Here is a screenshot from the GUI showing an LTM Policy rule which
Here is the resulting policy as it would appear in the /config/bigip.conf configuration file:
ltm policy first-party-cookies { requires { http } rules { r1 { actions { 0 { http-header response replace name Set-Cookie value "tcl:[HTTP::header Set-Cookie]; SameSite" } } conditions { 0 { http-header response name Set-Cookie not contains values { SameSite } } } } } status published strategy first-match }
- CruelSocketNimbostratus
I was having a ton of trouble with this until I figured out that irule variables scope is the whole connection, not just the response even if all your code is in `HTTP_RESPONSE`. The sample code appears to keep accumulating cookies in $newcookies over the life the of the connection.
Also, why use `[expr {!$foundSameSite} ]`? what's the benefit over just `!$foundSameSite`?
- Chris_OlsonNimbostratus
For those of you still struggling, we have a little more time (see link below). However, once released, other browsers are sure to follow suit. I am hoping F5 comes up with a feature similar to httpsonly and secure cookies which can be enabled or disabled in the peristence profile.
https://www.chromium.org/updates/same-site
- hooleylistCirrostratus
From that page:
- February, 2020: The SameSite-by-default and SameSite=None-requires-Secure behaviors will begin rolling out to Chrome 80 Stable for an initial limited population starting the week of February 17, 2020. We will be closely monitoring and evaluating ecosystem impact from this initial limited phase through gradually increasing rollouts.
- DannyGNimbostratus
We seem to be successful modifying the bigipserver persistence cookie just fine in the HTTP_RESPONSE. It seems HTTP_RESPONSE_RELEASE is needed if you are using ASM or some other module that is making modifications.
- HoolioRet. Employee
This updated iRule handles more scenarios including User-Agents which cannot handle SameSite=None:
- Adrian_PinaNimbostratus
Hi Chris_Olson,
If you only need to insert the SameSite attribute with the None value to every cookie, I think that the follwing iRule is simpler and could help you:
when HTTP_RESPONSE_RELEASE {foreach mycookie [HTTP::cookie names] {
HTTP::cookie attribute $mycookie insert "SameSite" "None"}}Kind regards.