This week's topic discusses how to validate application SessionIDs submitted by clients.
Initializing the SESSION collection with the setsid action.
Setsid
Description: Special-purpose action that initialises the SESSION
collection.
Action Group: Non-disruptive
Example:
# Initialise session variables using the session cookie value SecRule REQUEST_COOKIES:PHPSESSID !^$ "nolog,pass,setsid:%{REQUEST_COOKIES.PHPSESSID}"
Note
On first invocation of this action the collection will be empty (not taking the predefined variables into account - see initcol
for more information). On subsequent invocations the contents of the collection (session, in this case) will be retrieved from storage. After initialisation takes place the variable SESSIONID
will be available for use in the subsequent rules.This action understands each application maintains its own set of sessions. It will utilise the current web application ID to create a session namespace.
SESSION
This variable is a collection, available only after setsid
is executed. Example: the following example shows how to initialize a SESSION collection with setsid, how to use setvar to increase the session.score values, how to set the session.blocked variable and finally how to deny the connection based on the session:blocked value.
SecRule REQUEST_COOKIES:PHPSESSID !^$ "nolog,pass,setsid:%{REQUEST_COOKIES.PHPSESSID}" SecRule REQUEST_URI "^/cgi-bin/foo" \ "phase:2,t:none,t:lowercase,t:normalisePath,pass,log,setvar:session.score=+10" SecRule SESSION:SCORE "@gt 50" "pass,log,setvar:session.blocked=1" SecRule SESSION:BLOCKED "@eq 1" "log,deny,status:403"
The OWASP ModSecurity CRS includes an example ruleset that will validate SessionIDs as part of the optional_rules/modsecurity_crs_43_csrf_protection.conf file.
# # This rule will identify the outbound Set-Cookie SessionID data and capture it in a setsid # SecRule RESPONSE_HEADERS:/Set-Cookie2?/ "(?i:(j?sessionid|(php)?sessid|(asp|jserv|jw)?session[-_]?(id)?|cf(id|token)|sid)=([^\s]+)\;\s?)" "chain,phase:3,t:none,pass,nolog,capture,setsid:%{TX.6},setvar:session.sessionid=%{TX.6},setvar:session.valid=1" SecRule SESSION:SESSIONID "(.*)" "t:none,t:sha1,t:hexEncode,capture,setvar:session.csrf_token=%{TX.1}"
# # This rule file will identify outbound Set-Cookie/Set-Cookie2 response headers and # then initiate the proper ModSecurity session persistent collection (setsid). # The rules in this file are required if you plan to run other checks such as # Session Hijacking, Missing HTTPOnly flag, etc... # # # This rule set will identify subsequent SessionIDs being submitted by clients in # Request Headers. First we check that the SessionID submitted is a valid one # SecMarker BEGIN_SESSION_STARTUP SecRule REQUEST_COOKIES:'/(j?sessionid|(php)?sessid|(asp|jserv|jw)?session[-_]?(id)?|cf(id|token)|sid)/' ".*" "chain,phase:1,t:none,pass,nolog,auditlog,msg:'Invalid SessionID Submitted.',setsid:%{matched_var},setvar:tx.sessionid=%{matched_var},skipAfter:END_SESSION_STARTUP" SecRule SESSION:VALID "!@eq 1" "t:none" SecAction "phase:1,t:none,nolog,pass,setuid:%{session.username},setvar:session.sessionid=%{tx.sessionid}" SecMarker END_SESSION_STARTUP
Further description of this ruleset is discussed below.
Why should you try and validate SessionIDs sent by clients? I am reminded of President Ronald Reagan's famous saying "Trust, But Verify." Put it this way, just because a client sends a SessionID within the Request Header Cookie data does not mean that it is a valid one. There are numerous attacks where malicious clients will send in bogus SessionIDs with the most prevalent one being Credential/Session Prediction where an attacker manipulates the SessionID data in hopes that they can achieve a Session Hijacking attack. Another attack scenario that was just recently identified is the 'Padding Oracle' Crypto Attack against ASP.Net applications where the attacker sends in bogus encrypted SessionID. Based on the errors sent back out my the application they may be able to identify the crypto keys which would allow them to possibly decrypt sniffed cookie data or forge tickets.
The key concept with mitigating these types of SessionID attacks is to simply ask yourself - Do you trust the client or the application? The critical security moment in identifying many application session attacks is to initiate session collection data only when the application hands out a SessionID in a Set-Cookie response header. If you use the ModSecurity setsid action at this point, you can then also set a new variable within the collection to mark the SessionID as "valid" meaning that it is one that application actually handed out to a client. With this Session collection data saved, you can then use validation rules that will extract out any SessionID data submitted by client within Request Header Cookie data and verify if the "valid" variable has been sent. If this variable is not present, then you know that the client is sending a bogus SessionID.