diff --git a/rules/REQUEST-942-APPLICATION-ATTACK-SQLI.conf b/rules/REQUEST-942-APPLICATION-ATTACK-SQLI.conf index 821316034..51320802c 100644 --- a/rules/REQUEST-942-APPLICATION-ATTACK-SQLI.conf +++ b/rules/REQUEST-942-APPLICATION-ATTACK-SQLI.conf @@ -490,6 +490,53 @@ 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/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.msg=%{rule.msg}',\ + setvar:'tx.sql_injection_score=+%{tx.critical_anomaly_score}',\ + setvar:'tx.anomaly_score_pl1=+%{tx.critical_anomaly_score}',\ + setvar:'tx.%{rule.id}-OWASP_CRS/WEB_ATTACK/SQLI-%{MATCHED_VAR_NAME}=%{tx.0}'" + 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" @@ -1292,8 +1339,6 @@ 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}'" - - 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" # diff --git a/util/regression-tests/tests/REQUEST-942-APPLICATION-ATTACK-SQLI/942510.yaml b/util/regression-tests/tests/REQUEST-942-APPLICATION-ATTACK-SQLI/942510.yaml new file mode 100644 index 000000000..7b8a5dc87 --- /dev/null +++ b/util/regression-tests/tests/REQUEST-942-APPLICATION-ATTACK-SQLI/942510.yaml @@ -0,0 +1,24 @@ +--- + meta: + author: "Franziska Buehler" + description: None + enabled: true + name: 942510.yaml + tests: + - + test_title: 942510-1 + desc: "SQLi bypass detected: ticks or 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"