Skip to content

Commit

Permalink
feat(re2): rewrites rule 942130 with re2 support
Browse files Browse the repository at this point in the history
Signed-off-by: Felipe Zipitria <felipe.zipitria@owasp.org>
  • Loading branch information
fzipi committed Mar 12, 2022
1 parent b8f158f commit b1a0ca5
Show file tree
Hide file tree
Showing 5 changed files with 206 additions and 61 deletions.
63 changes: 54 additions & 9 deletions rules/REQUEST-942-APPLICATION-ATTACK-SQLI.conf
Original file line number Diff line number Diff line change
Expand Up @@ -561,20 +561,28 @@ SecRule ARGS_NAMES|ARGS|XML:/* "@rx (?i)(?:not\s+between\s+(?:(?:(?:'[^']*')|(?:
# Boolean-based SQL injection or tautology attack. Boolean values (True or False) are used to carry out
# this type of SQL injection. The malicious SQL query forces the web application to return a different result de-
# pending on whether the query returns a TRUE or FALSE result.
#
# Regexp generated from util/regexp-assemble/data/942130.data using Regexp::Assemble.
#
# The original 942130 was split in two rules:
# - 942130 targeting "true" tautologies (e.g. 1 = 1)
# - 942131 targeting "false" tautologies (e.g. 1 != 2)
#
# The regexp written at the initial rule on the chain is the original prefix from the 942130.data.
# When the prefix matches, we store the match to a new variable for comparing in the chained rule.
#
# The chained rule then uses the assembled regexp from 942130.data to check for the right hand side of the logical query.
#
# To rebuild the regexp:
# cd util/regexp-assemble
# ./regexp-assemble.py data/942130-re2.data
##
SecRule ARGS_NAMES|ARGS|XML:/* "@rx (?i)[\s'\"`()]*?\b([\d\w]+)\b[\s'\"`()]*?(?:<(?:=(?:[\s'\"`()]*?(?!\b\1\b)[\d\w]+|>[\s'\"`()]*?(?:\b\1\b))|>?[\s'\"`()]*?(?!\b\1\b)[\d\w]+)|(?:not\s+(?:regexp|like)|is\s+not|>=?|!=|\^)[\s'\"`()]*?(?!\b\1\b)[\d\w]+|(?:(?:sounds\s+)?like|r(?:egexp|like)|=)[\s'\"`()]*?(?:\b\1\b))" \
# ./regexp-assemble.py data/942130.data
#
SecRule ARGS_NAMES|ARGS|XML:/* "@rx (?i)[\s'\"`()]*?\b([\d\w]+)\b[\s'\"`()]*?" \
"id:942130,\
phase:2,\
block,\
capture,\
t:none,t:urlDecodeUni,t:replaceComments,\
msg:'SQL Injection Attack: SQL Tautology Detected',\
logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}: %{MATCHED_VAR}',\
msg:'SQL Injection Attack: SQL Boolean-based attack Detected',\
logdata:'Matched Data: %{TX.lhs_942130} found within %{MATCHED_VAR_NAME}',\
tag:'application-multi',\
tag:'language-multi',\
tag:'platform-multi',\
Expand All @@ -586,9 +594,46 @@ SecRule ARGS_NAMES|ARGS|XML:/* "@rx (?i)[\s'\"`()]*?\b([\d\w]+)\b[\s'\"`()]*?(?:
ver:'OWASP_CRS/3.4.0-dev',\
severity:'CRITICAL',\
multiMatch,\
setvar:'tx.sql_injection_score=+%{tx.critical_anomaly_score}',\
setvar:'tx.anomaly_score_pl2=+%{tx.critical_anomaly_score}'"
setvar:'tx.lhs_942130=%{TX.1}',\
chain"
SecRule MATCHED_VAR "@rx (?i)(?:(?:r(?:egexp|like)|<=>|=)[\s'\"`()]*?(?:\b%{tx.lhs_942130}\b)|(?:sounds\s+)?like[\s'\"`()]*?(?:\b%?%{tx.lhs_942130}%?\b))" \
"setvar:'tx.sql_injection_score=+%{tx.critical_anomaly_score}',\
setvar:'tx.anomaly_score_pl2=+%{tx.critical_anomaly_score}'"

# Rule Targeting logical inequalities that return TRUE (e.g. 1 != 2)
#
# The regexp written at the initial rule on the chain is the original prefix from the 942130.data.
# When the prefix matches, we store the match to a new variable for comparing in the chained rule.
#
# The chained rule then uses the assembled regexp from 942130.data to check for the right hand side of the logical query.
# To rebuild the regexp:
# cd util/regexp-assemble
# ./regexp-assemble.py data/942131.data
#
SecRule ARGS_NAMES|ARGS|XML:/* "@rx (?i)[\s'\"`()]*?\b([\d\w]+)\b[\s'\"`()]*?" \
"id:942131,\
phase:2,\
block,\
capture,\
t:none,t:urlDecodeUni,t:replaceComments,\
msg:'SQL Injection Attack: SQL Boolean-based attack detected',\
logdata:'Matched Data: %{TX.lhs_942131} found within %{MATCHED_VAR_NAME}',\
tag:'application-multi',\
tag:'language-multi',\
tag:'platform-multi',\
tag:'attack-sqli',\
tag:'OWASP_CRS',\
tag:'capec/1000/152/248/66',\
tag:'PCI/6.5.2',\
tag:'paranoia-level/2',\
ver:'OWASP_CRS/3.4.0-dev',\
severity:'CRITICAL',\
multiMatch,\
setvar:'tx.lhs_942131=%{TX.1}',\
chain"
SecRule MATCHED_VAR "!@rx (?i)(?:not\s+(?:r(?:egexp|like)[\s'\"`()]*?(?:\b%{tx.lhs_942131}\b)|like[\s'\"`()]*?(?:d\b%{tx.lhs_942131}\b))|(?:is\s+not|![<=>]|<[=>]?|>=?|\^)[\s'\"`()]*?(?:\b%{tx.lhs_942131}\b))" \
"setvar:'tx.sql_injection_score=+%{tx.critical_anomaly_score}',\
setvar:'tx.anomaly_score_pl2=+%{tx.critical_anomaly_score}'"

#
# -=[ SQL Function Names ]=-
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,36 +67,6 @@ tests:
output:
no_log_contains: id "942130"
- test_title: 942130-5
desc: "SQL Injection Attack: SQL Tautology"
stages:
- stage:
input:
dest_addr: 127.0.0.1
headers:
Host: localhost
User-Agent: OWASP ModSecurity Core Rule Set
Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5
method: GET
uri: "/?a=11!=1"
version: HTTP/1.1
output:
log_contains: id "942130"
- test_title: 942130-6
desc: "SQL Injection Attack: SQL Tautology"
stages:
- stage:
input:
dest_addr: 127.0.0.1
headers:
Host: localhost
User-Agent: OWASP ModSecurity Core Rule Set
Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5
method: GET
uri: "/?a=1!=11"
version: HTTP/1.1
output:
log_contains: id "942130"
- test_title: 942130-7
desc: "SQL Injection Attack: SQL Tautology"
stages:
- stage:
Expand All @@ -111,7 +81,7 @@ tests:
version: HTTP/1.1
output:
no_log_contains: id "942130"
- test_title: 942130-8
- test_title: 942130-6
desc: "SQL Injection Attack: SQL Tautology"
stages:
- stage:
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
---
meta:
author: "Felipe Zipitria"
description: SQL Tautology
enabled: true
name: 942131.yaml
tests:
- test_title: 942131-1
desc: "SQL Injection Attack: SQL Tautology"
stages:
- stage:
input:
dest_addr: 127.0.0.1
headers:
Host: localhost
User-Agent: OWASP ModSecurity Core Rule Set
Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5
method: GET
uri: "/?a=11!=1"
version: HTTP/1.1
output:
log_contains: id "942131"
- test_title: 942131-2
desc: "SQL Injection Attack: SQL Tautology"
stages:
- stage:
input:
dest_addr: 127.0.0.1
headers:
Host: localhost
User-Agent: OWASP ModSecurity Core Rule Set
Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5
method: GET
uri: "/?a=1!=11"
version: HTTP/1.1
output:
log_contains: id "942131"
- test_title: 942131-3
desc: "SQL Injection Attack: SQL Tautology"
stages:
- stage:
input:
dest_addr: 127.0.0.1
headers:
Host: localhost
User-Agent: OWASP ModSecurity Core Rule Set
Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5
method: GET
uri: "/?a=11!=11"
version: HTTP/1.1
output:
no_log_contains: id "942131"
58 changes: 37 additions & 21 deletions util/regexp-assemble/data/942130.data
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
##! This is a data file used to generate a regular expression for a CRS rule.
##! The generation of the regular expression happens with the help of
##! This is a data file used to generate a regular expression for a CRS rule.
##! The generation of the regular expression happens with the help of
##! util/regexp-assemble/regexp-assemble.py.
##! The ID of the rule in question is part of the file name of this data file.
##! Read more about the format of this data file and the use of the assembly
##! The ID of the rule in question is part of the file name of this data file.
##! Read more about the format of this data file and the use of the assembly
##! script in util/regexp-assemble/README.md.
##!
##! Lines starting with `##!` are comments and will be skipped,
##! empty lines will be ignored completely.
##! In addition, the quote character `'` at the beginning of a line will
##! cause the line to be interpreted as literal by the cmdline preprocessor only.
##!
##!
##! Five special comments are at your disposal to influence the assembled expression:
##! - `##!+`: the flag comment
##! - `##!^`: the prefix comment
Expand All @@ -21,21 +21,37 @@
##! - cmdline [windows|unix] (file scope)
##! Please refer to util/regexp-assemble/README.md for a full explanation


##! General comments:
##!
##! The idea behind this expressions is to capture simple logic based (un)equalities that
##! are used to quickly test SQL Logic that always returns TRUE (hence the term "SQL Tautology").

##! Prefix: captures the initial part that will be matched on the right hand side of the logicl construct.
##! This goes into the first rule of the chain:
##! [\s'\"`()]*?\b([\d\w]+)\b[\s'\"`()]*?

##!+ i

[\s'\"`()]*?\b([\d\w]+)\b[\s'\"`()]*?=[\s'\"`()]*?(?:\b\1\b)
[\s'\"`()]*?\b([\d\w]+)\b[\s'\"`()]*?<=>[\s'\"`()]*?(?:\b\1\b)
[\s'\"`()]*?\b([\d\w]+)\b[\s'\"`()]*?like[\s'\"`()]*?(?:\b\1\b)
[\s'\"`()]*?\b([\d\w]+)\b[\s'\"`()]*?rlike[\s'\"`()]*?(?:\b\1\b)
[\s'\"`()]*?\b([\d\w]+)\b[\s'\"`()]*?sounds\s+like[\s'\"`()]*?(?:\b\1\b)
[\s'\"`()]*?\b([\d\w]+)\b[\s'\"`()]*?regexp[\s'\"`()]*?(?:\b\1\b)
[\s'\"`()]*?\b([\d\w]+)\b[\s'\"`()]*?!=[\s'\"`()]*?(?!\b\1\b)[\d\w]+
[\s'\"`()]*?\b([\d\w]+)\b[\s'\"`()]*?<=[\s'\"`()]*?(?!\b\1\b)[\d\w]+
[\s'\"`()]*?\b([\d\w]+)\b[\s'\"`()]*?>=[\s'\"`()]*?(?!\b\1\b)[\d\w]+
[\s'\"`()]*?\b([\d\w]+)\b[\s'\"`()]*?<>[\s'\"`()]*?(?!\b\1\b)[\d\w]+
[\s'\"`()]*?\b([\d\w]+)\b[\s'\"`()]*?<[\s'\"`()]*?(?!\b\1\b)[\d\w]+
[\s'\"`()]*?\b([\d\w]+)\b[\s'\"`()]*?>[\s'\"`()]*?(?!\b\1\b)[\d\w]+
[\s'\"`()]*?\b([\d\w]+)\b[\s'\"`()]*?\^[\s'\"`()]*?(?!\b\1\b)[\d\w]+
[\s'\"`()]*?\b([\d\w]+)\b[\s'\"`()]*?is\s+not[\s'\"`()]*?(?!\b\1\b)[\d\w]+
[\s'\"`()]*?\b([\d\w]+)\b[\s'\"`()]*?not\s+like[\s'\"`()]*?(?!\b\1\b)[\d\w]+
[\s'\"`()]*?\b([\d\w]+)\b[\s'\"`()]*?not\s+regexp[\s'\"`()]*?(?!\b\1\b)[\d\w]+
##! These expressions try to match the logic using the operator,
##! so when the operator targets a TRUE operation, the initial match
##! should be present after the operator, logically meaning TRUE
##!
##! Examples:
##! '1' = '1'
##! 'f' like 'f'

##! This one will also match the "equal" part of '<=' and '>='
=[\s'\"`()]*?(?:\b%{tx.lhs_942130}\b)

<=>[\s'\"`()]*?(?:\b%{tx.lhs_942130}\b)

##! Like queries allow you to use wilcards: '%'

like[\s'\"`()]*?(?:\b%?%{tx.lhs_942130}%?\b)
sounds\s+like[\s'\"`()]*?(?:\b%?%{tx.lhs_942130}%?\b)

##! String based regexp. These don't use % as wildcard.
rlike[\s'\"`()]*?(?:\b%{tx.lhs_942130}\b)
regexp[\s'\"`()]*?(?:\b%{tx.lhs_942130}\b)

62 changes: 62 additions & 0 deletions util/regexp-assemble/data/942131.data
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
##! This is a data file used to generate a regular expression for a CRS rule.
##! The generation of the regular expression happens with the help of
##! util/regexp-assemble/regexp-assemble.py.
##! The ID of the rule in question is part of the file name of this data file.
##! Read more about the format of this data file and the use of the assembly
##! script in util/regexp-assemble/README.md.
##!
##! Lines starting with `##!` are comments and will be skipped,
##! empty lines will be ignored completely.
##! In addition, the quote character `'` at the beginning of a line will
##! cause the line to be interpreted as literal by the cmdline preprocessor only.
##!
##! Five special comments are at your disposal to influence the assembled expression:
##! - `##!+`: the flag comment
##! - `##!^`: the prefix comment
##! - `##!$`: the suffix comment
##! - `##!>`: the preprocessor comment
##! - `##!<`: the block preprocessor end comment
##!
##! Currently supported preprocessors:
##! - cmdline [windows|unix] (file scope)
##! Please refer to util/regexp-assemble/README.md for a full explanation


##! General comments:
##!
##! The idea behind this expressions is to capture simple logic based (un)equalities that
##! are used to quickly test SQL Logic that always returns FALSE.

##! Prefix: captures the initial part that will be unmatched on the right hand side of the logicl construct.
##! This goes into the first rule of the chain:
##! [\s'\"`()]*?\b([\d\w]+)\b[\s'\"`()]*?

##!+ i

##! These expressions try to match the logic using the negative operator,
##! so when the operator targets a false operation, the initial match
##! should *not* be present after the operator, effectively meaning TRUE
##!
##! Examples:
##! '1' <= '2'
##! 'a' not like 'b'
##!
##! SQL Comparison Operators: =, !=, <=, >=, <>, <, >, !>, !<, ^

\!=[\s'\"`()]*?(?:\b%{tx.lhs_942131}\b)
<>[\s'\"`()]*?(?:\b%{tx.lhs_942131}\b)
<[\s'\"`()]*?(?:\b%{tx.lhs_942131}\b)
\!<[\s'\"`()]*?(?:\b%{tx.lhs_942131}\b)
>[\s'\"`()]*?(?:\b%{tx.lhs_942131}\b)
\!>[\s'\"`()]*?(?:\b%{tx.lhs_942131}\b)
<=[\s'\"`()]*?(?:\b%{tx.lhs_942131}\b)
>=[\s'\"`()]*?(?:\b%{tx.lhs_942131}\b)
\^[\s'\"`()]*?(?:\b%{tx.lhs_942131}\b)

is\s+not[\s'\"`()]*?(?:\b%{tx.lhs_942131}\b)
not\s+like[\s'\"`()]*?(?:d\b%{tx.lhs_942131}\b)

##! String based regexp.

not\s+rlike[\s'\"`()]*?(?:\b%{tx.lhs_942131}\b)
not\s+regexp[\s'\"`()]*?(?:\b%{tx.lhs_942131}\b)

0 comments on commit b1a0ca5

Please sign in to comment.