Skip to content
This repository has been archived by the owner on May 14, 2020. It is now read-only.

Bypass the latest CRS v3.1.0 rules of SQL injection #1181

Closed
qazbnm456 opened this issue Sep 4, 2018 · 5 comments
Closed

Bypass the latest CRS v3.1.0 rules of SQL injection #1181

qazbnm456 opened this issue Sep 4, 2018 · 5 comments
Assignees

Comments

@qazbnm456
Copy link

qazbnm456 commented Sep 4, 2018

Type of Issue

False Negative

Description

Per #1167, I wanna raise more FNs in this thread.

Before getting into other FNs, I want to give out more information to #1167 so as to help the maintainers fix the issue quickly. There're two problems lead to those SQLi bypasses, and those evasions would only work with MySQL.
One is the lack of detections for legacy syntaxes, such as the ODBC escape syntax, which is accepted for ODBC compatibility (Ref: https://dev.mysql.com/doc/refman/5.5/en/expressions.html); the other one is the insufficient protection of libinjection due to the parsing process inside ticks. Return TYPE_FUNCTION when it encounters one of keywords of function names. You can clearly see the difference while parsing the following two quries. Because 1&{f1 doesn't in the fingerprint database, it has been flaged as a benign query.
image

Apart from that, I present additional SQLi bypasses in this issue here, and some of them also play with the same trick mentioned above together. Say, we have a code snippet that looks like this:

// Get input
$id = $_REQUEST['id']; 

// Check database
$query  = "SELECT first_name, last_name FROM users WHERE user_id = '$id';";
$result = mysql_query( $query ) or die( '<pre>' . mysql_error() . '</pre>' ); 
  • Following queries would bypass the protections of SQL injection attempts in PL1:
    • a'+(SELECT 1)+'
    • -1' AND 2<@ UNION/*!SELECT*/1, version()'
  • Following queries would bypass the protections of SQL injection attempts in PL2:
    • -1'<@=1 OR {a 1}=1 OR '
    • -1'<@=1 OR {x (select 1)}='1
    • a'+(SELECT 1)+'

These evasions work well with MySQL but may fail with other DBMS. I do the trick with the help of the <@ symbol because libinjection doesn't handle it well, especially with MySQL, and therefore, <@ can be used to bypass the detection of libinjection (Ref: https://github.com/client9/libinjection/blob/master/src/libinjection_sqli_data.h#L8681). Because 1&1o doesn't in the fingerprint database as well, it has been flaged as a benign query.
image

Some screenshots (The vulnerable web application is DVWA):
image
image

Your Environment

  • CRS version: v3.1/dev@806df0effbb89d2ba069b623162597e488119d2d
  • ModSecurity version: v3/master
  • Web Server and version: nginx/1.15.0
  • Operating System and version: macOS 10.14
@franbuehler
Copy link
Contributor

Summary
I think that our detection of these evasion techniques is not that bad, but unfortunately we do not have detection at PL1.
I am not sure, if we can change that, if we want to avoid FP at PL1.
I proposed a new rule

((?i:(['`])(?:[\w\s=_\-+{}()<@]+)?\1))

that checks for ticks and backticks with severity CRITICAL at PL2 as an addition to e WARNING rule 942110 at PL2.

Details

If I understand this issue correct, we have three problems, three evasion techniques, that can lead to SQLi detection bypasses (if I do not understand it correctly, please correct me, @qazbnm456):

  1. ODBC escape syntax: {}
  2. backticks: `` (same as mentioned in Bypass the latest crs v3.1.0-rc3 rules for SQL injection #1167) and ticks: ''
  3. <@

Number 1
Tested with: '1 AND {`if`1}=1'

Triggers 5 rules (no rule at PL1):
1 PL2 WARNING: [id "942110"] [msg "SQL Injection Attack: Common Injection Testing Detected"]
1 PL3 CRITICAL: [id "942490"] [msg "Detects classic SQL injection probings 3/3"]
1 PL3 WARNING: [id "942431"] [msg "Restricted SQL Character Anomaly Detection (args): # of special characters exceeded (6)"]
1 PL4 WARNING: [id "942432"] [msg "Restricted SQL Character Anomaly Detection (args): # of special characters exceeded (2)"]
1 PL4 CRITICAL: 920273"] [msg "Invalid character in request (outside of very strict set)"]

Individual paranoia level scores: 0, 3, 8, 8

Number 2
Test 2.1
Tested with: a' (SELECT 1) '

Triggers 3 rules (no rule at PL1):
1 PL2 WARNING: [id "942110"] [msg "SQL Injection Attack: Common Injection Testing Detected"]
1 PL4 WARNING: [id "942432"] [msg "Restricted SQL Character Anomaly Detection (args): # of special characters exceeded (2)"]
1 PL4 CRITICAL: [id "920273"] [msg "Invalid character in request (outside of very strict set)"]

Test 2.2
-1' AND 2<@ UNION/*!SELECT*/1, version()'
Would now be detected by new rule 942500 (PR #1326)!!!

Number 3
Test 3.1
Tested with: -1'<@=1 OR {a 1}=1 OR '
Triggers 6 rules:
PL2 WARNING: [id "942110"] [msg "SQL Injection Attack: Common Injection Testing Detected"]
PL3 CRITICAL: [id "942490"] [msg "Detects classic SQL injection probings 3/3"]
PL3 WARNING: [id "942431"] [msg "Restricted SQL Character Anomaly Detection (args): # of special characters exceeded (6)"]
PL3 WARNING: [id "942460"] [msg "Meta-Character Anomaly Detection Alert - Repetitive Non-Word Characters"]
PL4 WARNING: [id "942432"] [msg "Restricted SQL Character Anomaly Detection (args): # of special characters exceeded (2)"]
PL 4 CRITICAL: [id "920273"] [msg "Invalid character in request (outside of very strict set)"]

Individual paranoia level scores: 0, 3, 11, 8

Test 3.2
Tested with: -1'<@=1 OR {x (select 1)}='1
PL3 CRITICAL: [id "942490"] [msg "Detects classic SQL injection probings 3/3"]
PL3 WARNING: [id "942431"] [msg "Restricted SQL Character Anomaly Detection (args): # of special characters exceeded (6)"]
PL3 WARNING: [id "942460"] [msg "Meta-Character Anomaly Detection Alert - Repetitive Non-Word Characters"]
PL4 WARNING: [id "942432"] [msg "Restricted SQL Character Anomaly Detection (args): # of special characters exceeded (2)"]
PL 4 CRITICAL: [id "920273"] [msg "Invalid character in request (outside of very strict set)"]

Individual paranoia level scores: 0, 0, 11, 8

We have at least a rule at PL2 (942110) that triggers, except for the last request/test 3.2 (-1'<@=1 OR {x (select 1)}='1).
In general, I find the detection pretty good. But unfortunately not at PL1.
I am not sure if we can change that. I don't think so, if we want to avoid false positives at PL1.

Rule 942110 at PL2 detects ticks and backticks:
^\s*["'`;]+|["'`]+\s*$
Minimal string that matches is a single '.

String -1'<@=1 OR {x (select 1)}='1 (test 3.2) is the only test that does not trigger this rule, because the tick is not at the end of the line.

The rule 942110 at PL2 has only severity WARNING. Maybe this is because of possible FP with only one ' that matches.

What I would suggest:
I think a new CRITICAL rule at PL2 that checks for ticks, backticks. But there must be two of them (ticks, backticks):

((?i:(['`])(?:[\w\s=_\-+{}()<@]+)?\1))

Minimal string that triggers that rule is: ' '
But also 'bla' triggers this rule, or `bla`

I am not sure, if my proposed new rule is really better that the existing rule 942110.
And if the new rule deserves a CRITICAL at PL2.

The testcase 2.2 -1' AND 2<@ UNION/*!SELECT*/1, version()' (because of the comma) is not detected, but it's detected by the new rule 942500 from #1326!

What do you think of it?

@dune73
Copy link
Contributor

dune73 commented Apr 1, 2019

That sounds like a well thought through proposal. I think you should do this!

@theMiddleBlue theMiddleBlue added the PR available this issue is referenced by an active pull request label Apr 10, 2019
@fgsch fgsch removed the PR available this issue is referenced by an active pull request label Oct 21, 2019
@fgsch
Copy link
Contributor

fgsch commented Oct 21, 2019

Is this addressed by the above PR?

@dune73
Copy link
Contributor

dune73 commented Oct 21, 2019

@franbuehler is out for a couple of days. I asked her to return to this once she is back.

@franbuehler
Copy link
Contributor

Yes, this issue is solved by the mentioned PRs:
#1335
#1326

Not all SQLi bypasses are detected at PL1, but that's not possible I think.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants