[Owasp-modsecurity-core-rule-set] @within in crs_30 and similar (restricted extensions)

Brian Rectanus Brian.Rectanus at breach.com
Tue May 25 22:21:13 EDT 2010


[Apologies if anyone gets this >1x -- email server problems today]

On 05/25/2010 03:20 PM, Ryan Barnett wrote:
> On Tuesday 25 May 2010 17:41:55 modsec at enosis.com wrote:
> 
>> James:
> 
>>
> 
>> I suspect your problem is related to the earlier-reported
> 
>> REQUEST_HEADERS_NAMES problem in
> 
>>
> <https://lists.owasp.org/pipermail/owasp-modsecurity-core-rule-set/2010-Apr
> 
>> il/000357.html>
> 
>>
> 
>> The @within operator is misnamed for modsec's semantics.
> 
>> Or the documentation could be clearer. Or both.
> 
>>
> 
>> @within is (essentially) a simple linear string search:
> 
>> your argument ".do" was found in "foo .dos bar" IOW, the
> 
>> operation is what is more usually called "string match".
> 
>> Perhaps it should be called "@sm".
> 
>>
> 
> Yeah, we had some internal debates about naming operators. The thought
> was that the average Mod user was not necessarily a developer/programmer
> so they might not understand some of these terms. That is why we tried
> to name them in an easier (albeit not quite as accurate as you have
> pointed out) name.

Not "string match" as that is what @streq is.  This is a "substring
match", which @contains and @within are.  @within is similar to
@contains, but one major difference in that the matching operands are
reversed:

SecRule ARGS:foo "@contains bar" is "evaluate true if the foo argument
value contains 'bar' string".  So if foo=foobar, then bar would match as
it is a substring of "foobar".

SecRule ARGS:foo "@within bar" is "evaluate true if the foo argument
value is found within the string 'bar'".  So, if foo=foobar then there
is no match as there is no "foobar" substring in "bar".


> 
>> Because modsec provides "set" semantics ("Collections") and
> 
>> the appearance of tokenized input (such as your space-delimited
> 
>> %{tx.restricted.extensions} it's sensible for you (and by
> 
>> the evidence, the crs authors) to believe that @within will
> 
>> understand the context and magically switch between strings
> 
>> and tokens. Maybe it c/should in some cases.
> 
>>
> 
>> An operator like @containsWord does match on locale alphanum_
> 
>> tokens, but on the reverse of match and target for the rule
> 
>> variable and operator argument.

Eventually there will be a similar operator with boundaries.  But what
are those boundaries (whitespace, what localle, etc)?  That makes things
complex for configuration.

> 
>>
> 
>> @within is not, however, token based. So crs_30 rules like
> 
>> 960035 and 960038 will unexpectedly match even when the
> 
>> operation appears 'obviously' token-based. (e.g., on 960038,
> 
>> the ordinary and acceptable "Connection" header will be found
> 
>> @within "Proxy-Connection ...").
> 
>>
> 
>> One might think @pm would be a workable substitute for the
> 
>> rule 960038 case, but @pm apparently doesn't perform %{macro}
> 
>> substitution for its entire argument (@2.5.12). In the case
> 
>> of this rule, tho, the simple workaround is to use @pm and
> 
>> just put the restricted headers list directly into the rule.
> 
>>
> 
>> But in your case, with the longer list for rule 960035, @pm is
> 
>> out. As a workaround, perhaps use @pmFromFile. Just move the
> 
>> list to a one-per-line file of your making.

@pm and @pmFromFile are identical from a matching point of view.
@pmFromFile just accepts longer lists and also preserves whitespace
instead of tokenizing on whitespace.


> 
> I just updated the source templates for v2.0.7 and I opted to use
> boundary characters (/.../) when specifying the TX variables and then
> including them when we do the checks later. It is a similar concept to
> what Brian documented for @pmFromFile and IP addresses where you want to
> avoid partial matches -
> http://www.modsecurity.org/documentation/modsecurity-apache/2.5.12/modsecurity2-apache-reference.html#N11D9B


Yep, that is unfortunatly how it has to be done right now.

You could also do it like this:

SecAction "pass,nolog,setvar:tx.restricted_extensions='.dos|.foo|.bar|.baz'"
...
SecRule REQUEST_FILENAME "(\.[^\.]{1,10})$" \
  "capture,pass,setvar:TX.EXTENSION='tx.1|',..."
...
SecRule TX:EXTENSION "@within %{tx.restricted_extensions}|" \
  "deny,..."

Essentially, that grabs out the extension (1 to 10 chars), prefixes it
with a ".", appends a "|" (so you have ".do|" in TX:EXTENSION for
example), then matches this within ".do|.foo|.bar|.baz|" properly.

This looks nicer for extensions, but you could also do:

SecAction "pass,nolog,setvar:tx.restricted_extensions='dos|foo|bar|baz'"
...
SecRule REQUEST_FILENAME "\.([^\.]{1,10})$" \
  "capture,pass,setvar:TX.EXTENSION='|tx.1|',..."
...
SecRule TX:EXTENSION "@within |%{tx.restricted_extensions}|" \
  "deny,..."

Which looks better (more consistent) for other forms of data as well.
Or maybe use "," instead of "|"?  Non-regex geeks may like that better :)

-B

-- 
Brian Rectanus
Breach Security


More information about the Owasp-modsecurity-core-rule-set mailing list