0

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).

Derek Pollard
  • 115
  • 1
  • 6

1 Answers1

1

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"
Barry Pollard
  • 4,461
  • 14
  • 26
  • Well, the problem with this solution, I fear, is that the REQUEST_URI != REQUEST_FILENAME, and with that being said, the REQUEST_URI evaluates past the query string, which I do not need / want – Derek Pollard May 06 '16 at 15:07
  • REQUEST_URI = REQUEST_FILENAME + query string. Which is what you want I think. Have a look at those links in the first sentence of my reply. – Barry Pollard May 06 '16 at 16:05
  • I have, the way the server is structured, something with a request uri of `/this/here/and/there/` could actually be processed by `/page.php` – Derek Pollard May 06 '16 at 17:59
  • Yes but it's the request filename, not the file system filename this ultimately maps too, nor the requestor. So in that case it would return /this/there/and/there/. As per that page REQUEST_FILENAME: "This variable holds the relative request URL without the query string part (e.g., /index.php)." and REQUEST_URI: "This variable holds the full request URL including the query string data (e.g., /index.php?p=X)". So they are the exact same except one has query string data one other doesn't. – Barry Pollard May 06 '16 at 18:05