Open zachgalvin opened 1 year ago
coraza-caddy@v1.2.2
is way too old. Please do try https://github.com/corazawaf/coraza-caddy/releases/tag/v2.0.0-rc.3
Thanks for the quick response @jcchavezs ! I'll work on testing with the newer version this week, and update this issue once that is complete.
@jcchavezs I was able to reproduce this same issue on v2.0.0-rc.3.
Here is the setup I used to run the test:
The command I used to build caddy was this:
xcaddy build --with github.com/corazawaf/coraza-caddy/v2
After I did that, I ran caddy build-info
, and I got the following for coraza and coraza-caddy:
dep github.com/corazawaf/coraza-caddy/v2 v2.0.0-rc.3 h1:1oLZjJ500oUTaTH68Qurz6a3M/s0juMMkvV0WtO/RXc=
dep github.com/corazawaf/coraza-coreruleset v0.0.0-20230723190514-7bdcbcff3d5a h1:Lkmz2UckkFg86P65Xzet+bkt8jPMwNbIUtq73Z5Te9w=
dep github.com/corazawaf/coraza/v3 v3.0.3 h1:VmUFZ7ep74DmtF9bwOaLKUC6AEaXtI80S2I6BQenRs0=
I created a Caddyfile with the following:
{
debug
order coraza_waf first
}
http://127.0.0.1:5000 {
coraza_waf {
directives `
Include coraza.conf
Include crs-setup.conf.example
SecRuleEngine On
Include REQUEST-901-INITIALIZATION.conf
Include new_test.conf
Include REQUEST-949-BLOCKING-EVALUATION.conf
`
}
reverse_proxy http://127.0.0.1:5001
}
I created a really simple flask app that just returns a hello message for /test path that listens on http://127.0.0.1:5001 to use as my backend
from flask import Flask
app = Flask(__name__)
@app.route('/')
def hello():
return 'Hello, World!'
@app.route('/test', methods=['POST','GET'])
def test():
return 'Test!'
if __name__ == "__main__":
app.run(port=5001)
This could be replaced by anything though that listens on 127.0.0.1 on port 5001 and returns some sort of a response.
For the config files, I got coraza.conf from the main Coraza repo on GitHub. For REQUEST-901-INITIALIZATION.conf, REQUEST-949-BLOCKING-EVALUATION.conf, and crs-setup.conf.example, I grabbed the most recent version of each of those files from the Core Rule Set GitHub repo. Lastly, new_test.conf just has rule 921150 in it:
# Detect newlines in argument names.
# Checking for GET arguments has been moved to paranoia level 2 (921151)
# in order to mitigate possible false positives.
#
# This rule is also triggered by the following exploit(s):
# [ SAP CRM Java vulnerability CVE-2018-2380 - Exploit tested: https://www.exploit-db.com/exploits/44292 ]
#
SecRule ARGS_NAMES "@rx [\n\r]" \
"id:921150,\
phase:2,\
block,\
capture,\
t:none,t:htmlEntityDecode,\
msg:'HTTP Header Injection Attack via payload (CR/LF detected)',\
logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}: %{MATCHED_VAR}',\
tag:'application-multi',\
tag:'language-multi',\
tag:'platform-multi',\
tag:'attack-protocol',\
tag:'paranoia-level/1',\
tag:'OWASP_CRS',\
tag:'capec/1000/210/272/220/33',\
ver:'OWASP_CRS/4.0.0-rc1',\
severity:'CRITICAL',\
setvar:'tx.http_violation_score=+%{tx.critical_anomaly_score}',\
setvar:'tx.inbound_anomaly_score_pl1=+%{tx.critical_anomaly_score}'"
I ran my flask app script above to get that setup, and then I ran caddy with the following:
./caddy run --config Caddyfile
After that, I used the below Python script to send the request I mentioned in my first post to reproduce the error:
import requests
headers = {
'MIME-Version': '1.0',
'Content-Type': 'multipart/related;type="application/xop+xml";boundary= "awegerhnargaY";start="<<start>>"',
'Host': '127.0.0.1:5000',
'Content-Length': '45'
}
body = '''--awegerhnargaY
Content-ID: <<start>>
Content-Transfer-Encoding: 8bit
Content-Type: application/xop+xml;charset=utf-8;type="application/soap+xml"
<?xml version="1.0" encoding="UTF-8"?>
<test>
some text
<test>
--awegerhnargaY--
'''
p = requests.post('http://127.0.0.1:5000/test', data = body, headers = headers)
print(p.text)
print(p.status_code)
When I did that, I got the following error:
ERROR http.handlers.waf [client "127.0.0.1"] Coraza: Warning. HTTP Header Injection Attack via payload (CR/LF detected) [file "new_test.conf"] [line "1496"] [id "921150"] [rev ""] [msg "HTTP Header Injection Attack via payload (CR/LF detected)"] [data "Matched Data: \n found within ARGS_NAMES:--awegerhnargaY\nContent-ID: <<start>>\nContent-Transfer-Encoding: 8bit\nContent-Type: application/xop xml;charset: --awegerhnargaY\nContent-ID: <<start>>\nContent-T"] [severity "critical"] [ver "OWASP_CRS/4.0.0-rc1"] [maturity "0"] [accuracy "0"] [tag "application-multi"] [tag "language-multi"] [tag "platform-multi"] [tag "attack-protocol"] [tag "paranoia-level/1"] [tag "OWASP_CRS"] [tag "capec/1000/210/272/220/33"] [hostname ""] [uri "/test"] [unique_id "XQnGJJEgQuRilayD"]
@M4tteoP could you please have a look at this?
I'm testing some multipart/related XML POST requests on the Coraza WAF with Caddy right now, and the requests I'm sending are getting blocked by rule 921150 (Detect newlines in argument names). After further investigation, it looks like the body of the request is getting incorrectly added to the list of ARGS_NAMES
Here is an example request (use your own hostname):
In the example above, the rule fires because it sees "\r" after the initial boundary. That's definitely not an argument name though, so it seems like it thinks the whole body is composed of arguments. Do you all know what may be causing this? Or could you point me to the part of the code that controls this logic so that I can further dig in from there?
From looking at the code, it seems like ARGS_NAMES comes from tx.variables.argsPost with a Post request, but I wasn't able to figure out where that gets set.
Here is the version of coraza and the coraza-caddy plugin that I'm using: dep github.com/corazawaf/coraza-caddy v1.2.2 h1:rsA7c1m5H++V6pQSv220dMl3PTMEgrsped7E3cc3Zjk= dep github.com/corazawaf/coraza/v3 v3.0.0-20230117071831-8b909c7fc345 h1:4xW94n5Lah6ca8ROtP1g9fhVHc8RW5IyMnLVp3uzkUo=