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

Commit

Permalink
Merge pull request #1528 from lifeforms/split-942510
Browse files Browse the repository at this point in the history
SQLi: split 942510 into PL2 rule (backticks) and PL3 rule 942511 (ticks)
  • Loading branch information
lifeforms authored Aug 31, 2019
2 parents b3a6ccf + 3ccaea7 commit 42a2f6f
Show file tree
Hide file tree
Showing 3 changed files with 177 additions and 68 deletions.
151 changes: 105 additions & 46 deletions rules/REQUEST-942-APPLICATION-ATTACK-SQLI.conf
Original file line number Diff line number Diff line change
Expand Up @@ -508,52 +508,6 @@ SecRule REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES_NAMES|ARGS_NAME
setvar:'tx.sql_injection_score=+%{tx.critical_anomaly_score}',\
setvar:'tx.anomaly_score_pl1=+%{tx.critical_anomaly_score}'"

#
# -=[ Detect SQLi bypass: ticks and backticks ]=-
#
# Ticks and backticks can be used to bypass SQLi detection.
#
# Example:
# GET http://localhost/test.php?id=9999%20or+{`if`(2=(select+2+from+wp_users+where+user_login='admin'))}
#
# The minimum text between the ticks or backticks must be 2 (if, for example) and a maximum of 29.
# 29 is a compromise: The lower this number (29), the lower the probability of FP and the higher the probability of false negatives.
# In tests we got a minimum number of FP with {2,29}.
#
# Base64 encoding detection:
# (?:[A-Za-z0-9+/]{4})+ #match any number of 4-letter blocks of the base64 char set
# (?:[A-Za-z0-9+/]{2}== #match 2-letter block of the base64 char set followed by "==", together forming a 4-letter block
# | # or
# [A-Za-z0-9+/]{3}= #match 3-letter block of the base64 char set followed by "=", together forming a 4-letter block
# )?
#
# The minimal string that triggers this regexp is: 'if' or ` `
#
# The rule 942510 is related to 942110 which catches a single ' or `
#
SecRule REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES_NAMES|ARGS_NAMES|ARGS|XML:/* "@rx (?:(['`])((?:[\w\s=_\-+{}()<@]){2,29}|(?:[A-Za-z0-9+\/]{4})+(?:[A-Za-z0-9+\/]{2}==|[A-Za-z0-9+\/]{3}=)?)\1)" \
"id:942510,\
phase:2,\
block,\
capture,\
t:none,t:urlDecodeUni,\
msg:'SQLi bypass attempt by ticks or backticks detected.',\
logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}: %{MATCHED_VAR}',\
tag:'application-multi',\
tag:'language-multi',\
tag:'platform-multi',\
tag:'attack-sqli',\
tag:'OWASP_CRS',\
tag:'OWASP_CRS/WEB_ATTACK/SQL_INJECTION',\
tag:'WASCTC/WASC-19',\
tag:'OWASP_TOP_10/A1',\
tag:'OWASP_AppSensor/CIE1',\
tag:'PCI/6.5.2',\
ver:'OWASP_CRS/3.2.0',\
severity:'CRITICAL',\
setvar:'tx.sql_injection_score=+%{tx.critical_anomaly_score}',\
setvar:'tx.anomaly_score_pl1=+%{tx.critical_anomaly_score}'"


SecRule TX:EXECUTING_PARANOIA_LEVEL "@lt 2" "id:942013,phase:1,pass,nolog,skipAfter:END-REQUEST-942-APPLICATION-ATTACK-SQLI"
SecRule TX:EXECUTING_PARANOIA_LEVEL "@lt 2" "id:942014,phase:2,pass,nolog,skipAfter:END-REQUEST-942-APPLICATION-ATTACK-SQLI"
Expand Down Expand Up @@ -1375,6 +1329,59 @@ SecRule REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|!REQUEST_COOKIES:/_pk_ref/|REQU
setvar:'tx.sql_injection_score=+%{tx.critical_anomaly_score}',\
setvar:'tx.anomaly_score_pl2=+%{tx.critical_anomaly_score}'"


#
# -=[ Detect SQLi bypass: backticks ]=-
#
# Quotes and backticks can be used to bypass SQLi detection.
#
# Example:
# GET http://localhost/test.php?id=9999%20or+{`if`(2=(select+2+from+wp_users+where+user_login='admin'))}
#
# The minimum text between the ticks or backticks must be 2 (if, for example) and a maximum of 29.
# 29 is a compromise: The lower this number (29), the lower the probability of FP and the higher the probability of false negatives.
# In tests we got a minimum number of FP with {2,29}.
#
# Base64 encoding detection:
# (?:[A-Za-z0-9+/]{4})+ #match any number of 4-letter blocks of the base64 char set
# (?:[A-Za-z0-9+/]{2}== #match 2-letter block of the base64 char set followed by "==", together forming a 4-letter block
# | # or
# [A-Za-z0-9+/]{3}= #match 3-letter block of the base64 char set followed by "=", together forming a 4-letter block
# )?
#
# The minimal string that triggers this regexp is: `if`
#
# The rule 942510 is related to 942110 which catches a single ' or `
#
# The rule 942511 is similar to this rule, but triggers on normal quotes
# ('if'). That rule runs in paranoia level 3 or higher since it is prone to
# false positives in natural text.
#
SecRule REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES_NAMES|ARGS_NAMES|ARGS|XML:/* "@rx (?:`((?:[\w\s=_\-+{}()<@]){2,29}|(?:[A-Za-z0-9+\/]{4})+(?:[A-Za-z0-9+\/]{2}==|[A-Za-z0-9+\/]{3}=)?)`)" \
"id:942510,\
phase:2,\
block,\
capture,\
t:none,t:urlDecodeUni,\
msg:'SQLi bypass attempt by ticks or backticks detected.',\
logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}: %{MATCHED_VAR}',\
tag:'application-multi',\
tag:'language-multi',\
tag:'platform-multi',\
tag:'attack-sqli',\
tag:'OWASP_CRS',\
tag:'OWASP_CRS/WEB_ATTACK/SQL_INJECTION',\
tag:'WASCTC/WASC-19',\
tag:'OWASP_TOP_10/A1',\
tag:'OWASP_AppSensor/CIE1',\
tag:'PCI/6.5.2',\
tag:'paranoia-level/2',\
ver:'OWASP_CRS/3.2.0',\
severity:'CRITICAL',\
setvar:'tx.sql_injection_score=+%{tx.critical_anomaly_score}',\
setvar:'tx.anomaly_score_pl1=+%{tx.critical_anomaly_score}'"


SecRule TX:EXECUTING_PARANOIA_LEVEL "@lt 3" "id:942015,phase:1,pass,nolog,skipAfter:END-REQUEST-942-APPLICATION-ATTACK-SQLI"
SecRule TX:EXECUTING_PARANOIA_LEVEL "@lt 3" "id:942016,phase:2,pass,nolog,skipAfter:END-REQUEST-942-APPLICATION-ATTACK-SQLI"
#
Expand Down Expand Up @@ -1589,6 +1596,58 @@ SecRule REQUEST_BASENAME "@detectSQLi" \
setvar:'tx.anomaly_score_pl3=+%{tx.critical_anomaly_score}'"


#
# -=[ Detect SQLi bypass: quotes ]=-
#
# Quotes and backticks can be used to bypass SQLi detection.
#
# Example:
# GET http://localhost/test.php?id=9999%20or+{`if`(2=(select+2+from+wp_users+where+user_login='admin'))}
#
# The minimum text between the ticks or backticks must be 2 (if, for example) and a maximum of 29.
# 29 is a compromise: The lower this number (29), the lower the probability of FP and the higher the probability of false negatives.
# In tests we got a minimum number of FP with {2,29}.
#
# Base64 encoding detection:
# (?:[A-Za-z0-9+/]{4})+ #match any number of 4-letter blocks of the base64 char set
# (?:[A-Za-z0-9+/]{2}== #match 2-letter block of the base64 char set followed by "==", together forming a 4-letter block
# | # or
# [A-Za-z0-9+/]{3}= #match 3-letter block of the base64 char set followed by "=", together forming a 4-letter block
# )?
#
# The minimal string that triggers this regexp is: 'if'
#
# The rule 942511 is related to 942110 which catches a single ' or `
#
# The rule 942510 is similar to this rule, but triggers on backticks
# (`if`). That rule runs in paranoia level 2 or higher since the risk of
# false positives in natural text is still present but lower than this
# rule.
#
SecRule REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES_NAMES|ARGS_NAMES|ARGS|XML:/* "@rx (?:'((?:[\w\s=_\-+{}()<@]){2,29}|(?:[A-Za-z0-9+\/]{4})+(?:[A-Za-z0-9+\/]{2}==|[A-Za-z0-9+\/]{3}=)?)')" \
"id:942511,\
phase:2,\
block,\
capture,\
t:none,t:urlDecodeUni,\
msg:'SQLi bypass attempt by ticks detected.',\
logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}: %{MATCHED_VAR}',\
tag:'application-multi',\
tag:'language-multi',\
tag:'platform-multi',\
tag:'attack-sqli',\
tag:'OWASP_CRS',\
tag:'OWASP_CRS/WEB_ATTACK/SQL_INJECTION',\
tag:'WASCTC/WASC-19',\
tag:'OWASP_TOP_10/A1',\
tag:'OWASP_AppSensor/CIE1',\
tag:'PCI/6.5.2',\
tag:'paranoia-level/3',\
ver:'OWASP_CRS/3.2.0',\
severity:'CRITICAL',\
setvar:'tx.sql_injection_score=+%{tx.critical_anomaly_score}',\
setvar:'tx.anomaly_score_pl1=+%{tx.critical_anomaly_score}'"

SecRule TX:EXECUTING_PARANOIA_LEVEL "@lt 4" "id:942017,phase:1,pass,nolog,skipAfter:END-REQUEST-942-APPLICATION-ATTACK-SQLI"
SecRule TX:EXECUTING_PARANOIA_LEVEL "@lt 4" "id:942018,phase:2,pass,nolog,skipAfter:END-REQUEST-942-APPLICATION-ATTACK-SQLI"
#
Expand Down
Original file line number Diff line number Diff line change
@@ -1,24 +1,37 @@
---
meta:
author: "Franziska Buehler"
description: None
enabled: true
name: 942510.yaml
tests:
-
test_title: 942510-1
desc: "SQLi bypass detected: ticks or backticks"
meta:
author: "Franziska Buehler"
description: None
enabled: true
name: 942510.yaml
tests:
- test_title: 942510-1
desc: "SQLi bypass detected: backticks"
stages:
-
stage:
input:
dest_addr: 127.0.0.1
headers:
User-Agent: "ModSecurity CRS 3 Tests"
Host: localhost
method: GET
port: 80
uri: "/?'bla'"
version: HTTP/1.0
output:
log_contains: id "942510"
- stage:
input:
dest_addr: 127.0.0.1
headers:
User-Agent: "ModSecurity CRS 3 Tests"
Host: localhost
method: GET
port: 80
uri: "/?`bla`"
version: HTTP/1.0
output:
log_contains: id "942510"
- test_title: 942510-2
desc: "SQLi bypass detected: backticks"
stages:
- stage:
input:
dest_addr: 127.0.0.1
headers:
User-Agent: "ModSecurity CRS 3 Tests"
Host: localhost
method: GET
port: 80
uri: "/?'bla'"
version: HTTP/1.0
output:
no_log_contains: id "942510"
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
---
meta:
author: "Walter Hop"
description: None
enabled: true
name: 942511.yaml
tests:
- test_title: 942511-1
desc: "SQLi bypass detected: quotes"
stages:
- stage:
input:
dest_addr: 127.0.0.1
headers:
User-Agent: "ModSecurity CRS 3 Tests"
Host: localhost
method: GET
port: 80
uri: "/?`bla`"
version: HTTP/1.0
output:
no_log_contains: id "942511"
- test_title: 942511-2
desc: "SQLi bypass detected: quotes"
stages:
- stage:
input:
dest_addr: 127.0.0.1
headers:
User-Agent: "ModSecurity CRS 3 Tests"
Host: localhost
method: GET
port: 80
uri: "/?'bla'"
version: HTTP/1.0
output:
log_contains: id "942511"

0 comments on commit 42a2f6f

Please sign in to comment.