I'm trying to create a ModSecurity rule (I'm actually using Coraza, but it should be the same thing) to reject a request if it contains a JSON value in a POST request body. Here's what I have:
SecRule REQUEST_BODY "@contains \"foo\":\"bar\"" "id:1001,phase:2,deny,log"
The following request is not rejected:
curl -v -H "Content-Type: application/json" -X POST -d '{"foo":"bar"}' http://localhost
Even the following rule doesn't work:
SecRule REQUEST_BODY "@contains foo" "id:1001,phase:2,deny,log"
I see this in the log:
2023/10/31 17:28:18 [DEBUG] Evaluating operator: NO MATCH tx_id="WtmgMAOcaYrcfgawZRd" rule_id=1001 operator_function="@contains" operator_data="foo" arg=""
OWASP ModSecurity Core Rule Set Dev on Duty and Coraza Maintainer here. Assuming that you are running Coranza with the coraza.conf-recommended configuration, a fundamental rule that will have an impact on your outcome is the
200001:Being
application/jsonthe content type of the request, this rule will be triggered and the body processor that is going to handle your request will be set to the JSON one. Citing both Modsec and Coraza docs regarding theREQUEST_BODYvariable:Therefore, in that case the
REQUEST_BODYvariable is not going to be populated. What happens is that the body request is processed by the specific body processor that reads the JSON content, and splits it into args (specifically args_post).An example rule that would match
{"foo":"bar"}sent by the requestis the following:
Here we are looking for a specific json ARG (even ARGS_POST would work) with
fooas key and the value has to containbar.That being said, besides the previously quoted doc reference, I agree that it is not intuitive to figure out how the different body processor works. I'm taking notes to give some care to the Coraza doc about this topic!
Edit:
Example with caddy-coraza
This branch provides a small example based on caddy-coraza.
Steps to reproduce:
debuglog level:Most relevant logs show:
Alternatively:
Example with Go http-server
The main repo of Coraza comes with an http-server example. It is possible to tweak the default.conf file as below:
Curl request: