f5devcentral / irules-toolbox

This repository features a collection iRules of popular and/or critical mitigation updates, maintained by F5ers.
MIT License
41 stars 24 forks source link

SameSite=none is added for incompatible clients when restrict_irule_events is disabled #10

Open raZorTT opened 3 years ago

raZorTT commented 3 years ago

Hi team

I have noticed an issue using the SameSite iRule (v1.5) when I have ACCESS::restrict_irule_events disable configured and have the BIGIP configured as a SAML SP (although I suspect it will affect a wider range of APM cases). Despite the client being known as incompatible, the samesite=none is still being added.

I came across this when troubleshooting issues using iOS v12.5.x, which according to this known issue, will treat samesite=none as strict. When the client is redirected back to APM after authenticating with the IdP, the browser doesn't send the MRHSession cookie, so APM can't identify the existing session and denies the request.

The response from the initial request that hits the BIG-IP is fine

HTTP/1.0 302 Found
Server: BigIP
Connection: Close
Content-Length: 0
Location: /my.policy
Set-Cookie: LastMRH_Session=b4afa2ef; domain=mytest.xyz;path=/;secure
Set-Cookie: MRHSession=76e5ba2ee923caaa805a7024b4afa2ef; domain=mytest.xyz;path=/;secure

However, the response from /my.policy has the samesite=none added to the cookie

HTTP/1.1 200 OK
Server: BigIP
Content-Length: 5816
X-Frame-Options: DENY
Cache-Control: no-store
Set-Cookie: LastMRH_Session=b4afa2ef; domain=mytest.xyz;path=/;secure; samesite=none
Set-Cookie: MRHSession=9422a19a6fd9ac7aa764c3bbb4afa2ef; domain=mytest.xyz;path=/;secure; samesite=none

When restrict_irule_events is disabled, the internal APM events don't include a User-Agent header, which is normally fine. However, the SameSite iRule events are also triggered for each of those requests, and a blank user agent is passed into the checkSameSiteCompatible proc.

When the proc runs with a blank user agent it returns 1 by default because it no longer matches any of the incompatible agents.

# If the current user-agent didn't match any known incompatible browser list, assume it can handle SameSite=None 
return 1

As a result, the samesite_none_compatible variable is set to 1 and on the final HTTP_RESPONSE_RELEASE event, the samesite=none is added to the cookie.

I noticed that if you enable an incompatible client via the testing http_request event that's in the irule, it all works fine. Adding the header in that manner forces the incompatible UA to be inserted into the internal APM requests and the proc runs as expected.

raZorTT commented 3 years ago

I was thinking a way to resolve this would be to add a check to the HTTP_REQUEST event and try to identify if requests were part of the APM flow?

Would looking for .eui in the uri be sufficient? Or is there a better way to identify those events?

set apm_event [expr {[string first ".eui" [HTTP::uri]]} > 0 ? 1 : 0]

then adding an extra condition around the user-agent condition?

    # Check event is NOT part of APM flow (ACCESS::restrict_irule_events disable)
    if { $apm_event == 0 } {
        # Check if user-agent can handle samesite=none if we're removing samesite=none cookies or if we're setting samesite=none

        # If we're removing samesite=none cookies for incompatible browsers or we're setting samesite to none, 
        #   we need to check the user-agent to see if it's compatible with samesite=none
        if { $remove_samesite_for_incompatible_user_agents == 1 or $samesite_security eq "none"}{

            # Inspect user-agent once per TCP session for higher performance if the user-agent hasn't changed
            if { $samesite_none_compatible == 0 or $user_agent ne [HTTP::header value {User-Agent}]} {
                set user_agent [HTTP::header value {User-Agent}]
                set samesite_none_compatible [call checkSameSiteCompatible $user_agent]
                if { $samesite_debug }{
                    log local0. "$prefix Got \$samesite_none_compatible=$samesite_none_compatible and saved current \$user_agent: $user_agent"
                }
            }
        }
    }

Cheers, Simon