ModSecurity icon indicating copy to clipboard operation
ModSecurity copied to clipboard

Variable needed : REQUEST_HAS_BODY to avoid content-type evasion

Open touchweb-vincent opened this issue 1 month ago • 3 comments

Hello,

This issue followed this PR : https://github.com/coreruleset/coreruleset/pull/4347 and this comment : https://github.com/coreruleset/coreruleset/pull/4347#issuecomment-3556322624

`Since we cannot rely on REQUEST_BODY (and therefore not on REQUEST_BODY_LENGTH, which depends on REQUEST_BODY) for this use case, we are missing a REQUEST_HAS_BODY variable.

Would it be difficult to implement?

Given that you do not want to use STREAM_INPUT_BODY in PL1 (which I understand), I don’t see any other solution to handle this glaring security gap.`

touchweb-vincent avatar Nov 20 '25 07:11 touchweb-vincent

Hi @touchweb-vincent,

thanks for reporting this.

What I don't understand here that you wrote:

we cannot rely on REQUEST_BODY (and therefore not on REQUEST_BODY_LENGTH

Why do you think that we can't rely on REQUEST_BODY_LENGTH. I think that can be used in case of both engine, v2 and v3 support it.

airween avatar Nov 25 '25 14:11 airween

Hi @airween

Because, from what I understand from the documentation, these variables are only available when the URLENCODED processor is used, which limits far too much of the operational scope expected by the intended PR.

Holds the raw request body. This variable is available only if the URLENCODED request body processor was used, which will occur by default when the application/x-www-form-urlencoded content type is detected, or if the use of the URLENCODED request body parser was forced. 

touchweb-vincent avatar Nov 25 '25 17:11 touchweb-vincent

Please take a look at this rule:

SecRule REQUEST_BODY_LENGTH "@gt 0" \
    "id:100,\
    phase:2,\
    deny,\
    t:none,\
    msg:'Request body length is %{REQUEST_BODY_LENGTH}'"

This work in case of GET request (but of course this rule does not triggered then). And also works in case of application/json:

curl -H "Content-Type: application/json" -d "{}" http://localhost

See the log:

ModSecurity: Warning. Operator GT matched 0 at REQUEST_BODY_LENGTH. [file "/home/airween/src/coreruleset/owasp-crs.load"] [line "47"] [id "100"] [msg "Request body length is 2"] [hostname "localhost"] [uri "/"] [unique_id "aSa-ZSXVD4JwYrX7GUZWtAAAAQE"]

these variables are only available when the URLENCODED processor is used

That restriction regards to REQUEST_BODY variable, and only in case of mod_security2 Apache module. libmodsecurity3 has a known bug, namely REQUEST_BODY is always presented (but you're right, a rule writer can't rely on that).

In fact REQUEST_BODY_LENGTH is available.

But the problem is something different: just imagine you send a request with application/json CT. In that case you can't send an empty body, because the parser will fail. '' is not a valid JSON. '' is not a valid XML, and not a valid multipart request. So if the CT header is not www-urlencoded, then the body must contains some bytes.

airween avatar Nov 26 '25 08:11 airween