Snort rules regex matching

19.2k views Asked by At

I want to generate an event in snort whenever someone visits a URL structured like

site/year2015.pdf
site/year2014.pdf
:
:
site/year2000.pdf

Instead of writing multiple snort rules as more URLs will be added over years I thought of utilizing PERC. The rule is written as.

alert tcp any any -> any any(msg:"PDF is being downloaded"; pcre:"(/.*site\/year\d\d\d\d\.pdf)/i"; sid: 100003; rev:3;)

I tried many different ways of inserting the regex in the rule above but it always fails to parse it. The Regex is doing fine what I want it to do here. The whole thing starts to fail because it does not start cause of rule not being parsed.

Error received is

Error: /etc/snort/rules/assignment.rules Line 3 => unable to parse pcre regex "(/.*site\/year\d\d\d\d\.pdf)/i"
Fatal Error Quitting..
2

There are 2 answers

0
tripleee On BEST ANSWER

The (slightly crazy) syntax is pcre:"/regex/flags". The parentheses you wanted to put in there are superfluous anyway. You also need to escape any slash which is part of the actual regex, like in the example.

alert tcp any any -> any any(msg:"PDF is being downloaded"; pcre:"/.*site\/year\d\d\d\d.pdf/i"; sid: 100003; rev:3;)

... though probably you should remove the superfluous wildcard .* and add an anchor $ at the end, and also escape the dot to make it literal. You might also want to use a quantifier to specify exactly four repetitions of a digit.

alert tcp any any -> any any(msg:"PDF is being downloaded"; pcre:"/site\/year\d{4}\.pdf$/i"; sid: 100003; rev:3;)

Are you really sure you want the /i flag to make the match case-insensitive?

1
Barton Chittenden On

As tripleee mentioned, your parentheses were misplaced... but I also think that it's worth mentioning that since these are Perl regular expressions, you have some flexibility in the delimiters that you're using for the regular expression:

The syntax

pcre:[!]"(/<regex>/|m<delim><regex><delim>)[ismxAEGRUBPHMCOIDKYS]";

indicates that instead of using the traditional / delimiter, you may use the m operator (short for 'match'), followed by alternate delimiters... I'm using [ and ] in this case:

msg:"PDF is being downloaded"; pcre:"m[site/year\d{4}\.pdf$]i"; sid: 100003; rev:3;)

This doesn't buy you much in this particular case (because you're only one directory deep), but a more deeply nested directory would quickly become unreadable with all of the escaped / characters.