[Snort-sigs] Generic SQL injection false positives

Matt Olney molney at ...435...
Fri Jan 8 12:20:17 EST 2010


First,

I wanted to let you know this is still on my plate, but I just haven't
gotten to it yet.  I have not forgotten about it though.

Second, I sent this email, and it was meant to have been copied to the
list (but I failed), so here is the info:

OK, here is how PCRE works...it addresses whatever buffer you tell it
to.  It looks at the exact same buffer data that the content match
work on.  In fact, if you use the /R flag, you will start your PCRE
work at the DOE pointer (that is, the end of the last successful
content match, PCRE or byte_jump).  Here is the switch code from
sp_pcre.c:

    while(*opts != '\0') {
        switch(*opts) {
        case 'i':  compile_flags |= PCRE_CASELESS;            break;
        case 's':  compile_flags |= PCRE_DOTALL;              break;
        case 'm':  compile_flags |= PCRE_MULTILINE;           break;
        case 'x':  compile_flags |= PCRE_EXTENDED;            break;

            /*
             * these are pcre specific... don't work with perl
             */
        case 'A':  compile_flags |= PCRE_ANCHORED;            break;
        case 'E':  compile_flags |= PCRE_DOLLAR_ENDONLY;      break;
        case 'G':  compile_flags |= PCRE_UNGREEDY;            break;

            /*
             * these are snort specific don't work with pcre or perl
             */
        case 'R':  pcre_data->options |= SNORT_PCRE_RELATIVE; break;
        case 'U':  pcre_data->options |= SNORT_PCRE_HTTP_URI; break;
        case 'B':  pcre_data->options |= SNORT_PCRE_RAWBYTES; break;
        case 'P':  pcre_data->options |= SNORT_PCRE_HTTP_BODY;  break;
        case 'O':  pcre_data->options |= SNORT_OVERRIDE_MATCH_LIMIT; break;
        case 'H':  pcre_data->options |= SNORT_PCRE_HTTP_HEADER;  break;
        case 'M':  pcre_data->options |= SNORT_PCRE_HTTP_METHOD;  break;
        case 'C':  pcre_data->options |= SNORT_PCRE_HTTP_COOKIE;  break;

The top two sets are your standard PCRE options.  The bottom calls are
the Snort specific ones.  In this case, if you wanted to work on the
HTTP_URI buffer you would have something to the effect of
pcre:/\?.+SELECT/Ui.  Since you would be in the uri, you wouldn't have
to worry about line breaks.

As to evasion cases, we could work through them with SO rules, but I
wouldn't take the overhead hit on that for a generic detection rule.
My goal in rewriting these will be to get the performance right, catch
your standard sql inject statements, and handle those evasion cases I
can.  I may go ahead and throw together some rules that looks to
detect some of the evasion cases you are talking about.

If you guys have specific pcaps you want me to include in testing,
feel free to send them over.

Matt

On Tue, Dec 29, 2009 at 9:03 PM, Guise McAllaster
<guise.mcallaster at ...2420...> wrote:
> My understanding is that the pcre directives will match against the
> current data buffer (how large is it? I don't know but probably a
> config setting).  I could be wrong and it behaves like normal pcre
> where it will match only on a single line (i.e. data separated by
> newline character(s)) unless the 'm' (multi-line) modifier is used
> (e.g. "/select.*from/m").  SourceFire, please clarify if possible.
> (Thank you.)
>
> Nevertheless, your pcre is still flawed since it is anchored at the
> beginnings and ends of the buffer (or line whichever is the case).
> Perhaps you mean to use words boundaries.  Something like:
>
> pcre:"/\bupdate\b";
>
> Hope these help.
>
> Guise
>
> P.S. SourceFire has already admitted that things like "+" or "/**/"
> are not removed from the normalized buffer so you are correct, they
> can be used to trivially bypass snorts.
>
>
>
>
> On 12/29/09, Paul Schmehl <pschmehl_lists at ...3425...> wrote:
>> OK, if you change the rule to use uricontent instead of content, then
>> you'll avoid missing content that will appear after being normalized.
>> However, I'm not convinced that normalizing will strip out sql comments
>> like /**/.  If I'm correct in that, then even uricontent:'update"; nocase;
>> pcre:"/^update$/i" will miss things like UP/**/DATE.  If uricontent
>> doesn't match, pcre will never be tested, because content/uricontent
>> matches are linear and from left to right.  The first content/uricontent
>> must match something in the packet or the rest of the rule will be ignored.
>>
>> Anchoring the sql query syntax (e.g. pcre:"/^update$/i"; forces a match on
>> only that word and no others.  ISTM that would be what you want if you're
>> trying to catch sql injection and avoid false positives.
>>
>> --On December 29, 2009 9:28:35 AM -0600 Guise McAllaster
>> <guise.mcallaster at ...2420...> wrote:
>>
>>> Sir, let me clarify a few thing.  Firstly, "content" matches will not
>>> match against a normalized buffer so you are correct that data such as
>>> "D/**/ROP, DR/**/OP or DRO/**/P" will bypass a content match looking for
>>> "DROP".  However, using uricontent will match the normalized buffer
>>> which should (hopefully -- this is what we need clarifications on as to
>>> what specific the normalization is) have removed such things as "%20",
>>> "+", and "/**/".
>>>
>>> Now, as for your comments, I am confused.  You say, "If you use
>>> content:"foo"; nocase; first, and then pcre:"/^foo$/i"; next, content
>>> will never match, so pcre will never be checked."  Yet data containing
>>> "foo" will match the content check and snort will move on to chech the
>>> PCRE match.  Howevers, the PCRE is not correctly what you want I
>>> think.  It will only match "foo" and nothing else (e.g.
>>> "<beginning_of_line>foo<end_of_line>").  For example, "0foo", "bfoo",
>>> "foobar", and "foosball", will not match.
>>>
>>> As an aside, thank you Matt and VRT for looking in to these rules as
>>> they are a mountain of false positives in my environment and thus not
>>> useful in the currently.
>>>
>>> Guise
>>>
>>>
>>> On Tue, Dec 29, 2009 at 2:50 AM, Paul Schmehl <pschmehl_lists at ...3443....>
>>> wrote:
>>>
>>> Now that I've had some time to think about this, I do not think that
>>> normalization will remove these.  I suspect that they will be passed to
>>> the sql server.
>>>
>>> The problem with trying to detect them is this.  If you use
>>> content:"foo"; nocase; first, and then pcre:"/^foo$/i"; next, content
>>> will never match, so pcre will never be checked.  But to catch every
>>> possible instance you would have to try to match on the /**/ first, then
>>> strip it from the content and match on update.  I don't think snort can
>>> do that.
>>>
>>> To bypass detection, I could use any one of the following: D/**/ROP,
>>> DR/**/OP or DRO/**/P.  How would you test for all those instances?  In
>>> a simple rule that's designed to detect "generic" sql injection, I think
>>> you stick with detecting update and set.
>>>
>>> If you want to catch instances of comments inserted into sql injection,
>>> you would need a separate rule that attempts to detect the evasion.
>>> Considering that urls normally have forward slashes in them, that would
>>> not be easy to do.
>>>
>>>
>>>
>>>
>>> --On December 28, 2009 6:40:42 PM -0600 Paul Schmehl
>>> <pschmehl_lists at ...3425...> wrote:
>>>
>>>
>>> I believe normalization will remove those as well, but someone from
>>> Sourcefire will have to confirm that.
>>>
>>> --On December 29, 2009 12:15:53 AM +0000 Guise McAllaster
>>> <guise.mcallaster at ...2420...> wrote:
>>>
>>>
>>> Sure:
>>>
>>> http://ferruh.mavituna.com/sql-injection-cheatsheet-oku/
>>>
>>> Search for "/**/"
>>>
>>> A good point somebody says is that we need to know what exactly the
>>> URL normalization is done so we can know what it eliminates.  Some
>>> like "%20" and "+" or "++" are sure recognized but others?  What are
>>> they?
>>>
>>> Snort has been victim to some bypasses in the past (no offense, VRT).
>>>
>>> Guise
>>>
>>> On 12/28/09, Paul Schmehl <pschmehl_lists at ...3425...> wrote:
>>>
>>> Can you provide an example of that?
>>>
>>> --On December 28, 2009 4:15:20 PM -0600 Guise McAllaster
>>> <guise.mcallaster at ...2420...> wrote:
>>>
>>>
>>>
>>> From what I've seen, some SQLi will work using "/**/" instead of
>>> spaces.  Other bypasses are possible as well I thinks.  Others want to
>>> contribute some useful bypasses to spaces?
>>>
>>> Guise
>>>
>>> On 12/28/09, Paul Schmehl <pschmehl_lists at ...3425...> wrote:
>>>
>>> --On December 28, 2009 12:10:37 PM -0600 Matt Olney
>>> <molney at ...435...> wrote:
>>>
>>>
>>> I see a lot of false positive for generic SQL injection rules.  For
>>> example, SID 13514 shown here:
>>>
>>> alert tcp $EXTERNAL_NET any -> $HTTP_SERVERS $HTTP_PORTS (msg:"SQL
>>> generic sql update injection attempt"; flow:established,to_server;
>>> content:"update"; nocase; pcre:"/update[^\n]*set/i"; metadata:policy
>>> security-ips drop, service http;
>>> reference:url,www.securiteam.com/securityreviews/5DP0N1P76E.html;
>>> classtype:web-application-attack; sid:13514; rev:4;)
>>>
>>> Alas it alerts for normal traffic like this:
>>>
>>> GET /get_updates_1/assessment/frameset_yellow.asp  HTTP/1.1
>>>
>>>
>>> I don't see how a sql injection attempt is going to begin with any
>>> character other than a space preceding it.  How would the sql engine
>>> be able to parse that?  ISTM that the update could simply be anchored
>>> on both sides; e.g pcre:"$update^/i";  For update to work, the only
>>> thing that can be on either side of it is a non-alpha character or a
>>> single quote, which the sql parser will discard.  If you want to
>>> include set (which makes sense), I would make it a separate
>>> detection.  A typical update statement would be UPDATE table SET
>>> blah='foo' where blah='bar' or blah like '%doo%';
>>>
>>> Something like this would be better, in my opinion.
>>>
>>> alert tcp $EXTERNAL_NET any -> $HTTP_SERVERS $HTTP_PORTS (msg:"SQL
>>> generic sql update injection attempt"; flow:established,to_server;
>>> content:"update"; nocase; pcre:"/$update^/i"; content:"set"; nocase;
>>> pcre:"/$set^/i"; metadata:policy security-ips drop, service http;
>>> reference:url,www.securiteam.com/securityreviews/5DP0N1P76E.html;
>>> classtype:web-application-attack; sid:13514; rev:5;)
>>>
>>> Mind you, I haven't tested it, but it would certainly eliminate the
>>> false positive given in the example.
>>>
>>> Paul Schmehl, If it isn't already
>>> obvious, my opinions are my own
>>> and not those of my employer.
>>> ******************************************
>>> WARNING: Check the headers before replying
>>>
>>>
>>> ---------------------------------------------------------------------
>>> -- ------- This SF.Net email is sponsored by the Verizon Developer
>>> Community Take advantage of Verizon's best-in-class app development
>>> support A streamlined, 14 day to market process makes app
>>> distribution fast and easy Join now and get one step closer to
>>> millions of Verizon customers http://p.sf.net/sfu/verizon-dev2dev
>>> _______________________________________________
>>> Snort-sigs mailing list
>>> Snort-sigs at lists.sourceforge.net
>>> https://lists.sourceforge.net/lists/listinfo/snort-sigs
>>>
>>>
>>>
>>>
>>>
>>> Paul Schmehl, If it isn't already
>>> obvious, my opinions are my own
>>> and not those of my employer.
>>> ******************************************
>>> WARNING: Check the headers before replying
>>>
>>>
>>>
>>>
>>>
>>>
>>>
>>>
>>> Paul Schmehl, If it isn't already
>>> obvious, my opinions are my own
>>> and not those of my employer.
>>> ******************************************
>>> WARNING: Check the headers before replying
>>>
>>>
>>>
>>>
>>> Paul Schmehl, If it isn't already
>>> obvious, my opinions are my own
>>> and not those of my employer.
>>> ******************************************
>>> WARNING: Check the headers before replying
>>>
>>>
>>>
>>
>>
>>
>> Paul Schmehl, If it isn't already
>> obvious, my opinions are my own
>> and not those of my employer.
>> ******************************************
>> WARNING: Check the headers before replying
>>
>>
>
> ------------------------------------------------------------------------------
> This SF.Net email is sponsored by the Verizon Developer Community
> Take advantage of Verizon's best-in-class app development support
> A streamlined, 14 day to market process makes app distribution fast and easy
> Join now and get one step closer to millions of Verizon customers
> http://p.sf.net/sfu/verizon-dev2dev
> _______________________________________________
> Snort-sigs mailing list
> Snort-sigs at lists.sourceforge.net
> https://lists.sourceforge.net/lists/listinfo/snort-sigs
>




More information about the Snort-sigs mailing list