Security – Modsecurity check REQUEST_URI without query parameters

apache-2.2apache-2.4mod-securitySecurity

Currently, I am using Modsecurity XSS prevention, but I'm having a hard time understanding how exactly I can restrict what I'm checking for in the REQUEST_URI variable.

My Example:

#
# -=[ XSS Filters - Category 3 ]=-
# XSS vectors making use of Javascripts URIs, e.g., <p style="background:url(javascript:alert(1))">
#
SecRule REQUEST_URI|ARGS "(?i)((?:=|U\s*R\s*L\s*\()\s*[^>]*\s*S\s*C\s*R\s*I\s*P\s*T\s*:|&colon;|[\s\S]allowscriptaccess[\s\S]|[\s\S]src[\s\S]|[\s\S]data:text\/html[\s\S]|[\s\S]xlink:href[\s\S]|[\s\S]base64[\s\S]|[\s\S]xmlns[\s\S]|[\s\S]xhtml[\s\S]|[\s\S]style[\s\S]|<style[^>]*>[\s\S]*?|[\s\S]@import[\s\S]|<applet[^>]*>[\s\S]*?|<meta[^>]*>[\s\S]*?|<object[^>]*>[\s\S]*?)" "id:'973338',phase:2,t:none,rev:'1',ver:'OWASP_CRS/2.2.9',maturity:'1',accuracy:'8',t:urlDecodeUni,t:htmlEntityDecode,t:jsDecode,t:cssDecode,log,capture,tag:'OWASP_CRS/WEB_ATTACK/XSS',tag:'WASCTC/WASC-8',tag:'WASCTC/WASC-22',tag:'OWASP_TOP_10/A2',tag:'OWASP_AppSensor/IE1',tag:'PCI/6.5.1',msg:'XSS Filter - Category 3: Javascript URI Vector',logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}: %{MATCHED_VAR}',severity:'2',setvar:'tx.msg=%{rule.msg}',setvar:tx.xss_score=+%{tx.critical_anomaly_score},setvar:tx.anomaly_score=+%{tx.critical_anomaly_score},setvar:tx.%{rule.id}-OWASP_CRS/WEB_ATTACK/XSS-%{matched_var_name}=%{tx.0}"

In the above example, the regex checks for certain tags and if found, stops the requests, logs the attempt and then throws a 403 forbidden.

That's all fine, but I have a specific URL that looks something like this:

/chart.php?this=haha&style=testStyle

Where &style= makes ModSecurity throw an error and stop the request.

Similarly, they have a rule that checks for just style=,

So my question is, how can I alter REQUEST_URI in a way (inside the ModSecurity rules) so that the rule only checks for everything before the ? (query string).

Best Answer

You could use the REQUEST_FILENAME variable instead of REQUEST_URI.

You are recommended not to directly edit the OWASP CRS rules themselves but instead to add extra rules to adjust them. This allows you to upgrade the CRS and still keep your rules. Here you could do this by adding the following config after you load all the OWASP CRS rules files to adjust this rule:

SecRuleUpdateTargetById 973338 REQUEST_FILENAME REQUEST_URI

However this will reduce this rule for all request when you may only want to do this for this one URL in which case a better method may be to turn this rule off only for this URL by adding the following rule before you load the OWASP CRS rules files (note the id needs to be unique so if you already have a rule 1 then pick a unique if here):

SecRule REQUEST_FILENAME chart.php "phase:2,nolog,id:1,ctl:ruleRemoveById=973338,pass"

And yes, before you ask, it is annoying that some overrides are specified after the rules and others, that use ctl, need to be specified before.

If you have multiple rules to disable you can use syntax like this:

SecRule REQUEST_FILENAME chart.php "phase:2,nolog,id:1,ctl:ruleRemoveById=973338,ctl:ruleRemoveById=973306,pass"
Related Topic