Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

REQUEST_BODY_LENGTH is only available in phase 3, causing rule execution issues in earlier phases #3346

Closed
Ablfantastic opened this issue Mar 5, 2025 · 4 comments
Labels
3.x Related to ModSecurity version 3.x

Comments

@Ablfantastic
Copy link

Ablfantastic commented Mar 5, 2025

REQUEST_BODY_LENGTH is only available in phase 3, causing rule execution issues in earlier phases

Describe the bug

REQUEST_BODY_LENGTH is only available in phase 3, but certain security rules (e.g., request body validation) execute in phase 2. This timing issue makes it impossible to properly use REQUEST_BODY_LENGTH to control rule execution before request body validation occurs. This prevents rules from being dynamically disabled or modified based on body size before enforcement.

Logs and dumps

[174116811769.062398] [/admin/campus/curso/394/edit?destination=catalogo/curso/394/ver] [4] (Rule: 10019) Executing operator "Gt" with param "100" against REQUEST_BODY_LENGTH.
[174116811769.062398] [/admin/campus/curso/394/edit?destination=catalogo/curso/394/ver] [9] Target value: "" (Variable: REQUEST_BODY_LENGTH)
[174116811769.062398] [/admin/campus/curso/394/edit?destination=catalogo/curso/394/ver] [4] Rule returned 0.

To Reproduce
Steps to reproduce:

Set a rule that attempts to remove another rule based on REQUEST_BODY_LENGTH:

SecRule REQUEST_BODY_LENGTH "@gt 100" "id:10019,phase:1,nolog,pass,ctl:ruleRemoveById=200002"

Observe that REQUEST_BODY_LENGTH is only assigned a value in phase 3.

A rule like 200002 (executing in phase 2) cannot be dynamically removed based on body size, as the value is not available yet.

This issue is problematic for setups where large request bodies need to be conditionally exempt from strict ModSecurity enforcement. If REQUEST_BODY_LENGTH remains unavailable in phase 1 or 2, certain security mechanisms will always trigger before exclusions can be applied.

Would it be possible to make REQUEST_BODY_LENGTH accessible earlier in the request processing cycle?

Server:

  • ModSecurity version (and connector): The docker image I am using is owasp/modsecurity-crs:4.10.0-nginx-202501270601
  • WebServer: nginx/1.22.1
  • OS (and distro): Linux, alpine:latest

Rule Set (please complete the following information):

  • Running any public or commercial rule set? -
  • What is the version number? -
@Ablfantastic Ablfantastic added the 3.x Related to ModSecurity version 3.x label Mar 5, 2025
@airween
Copy link
Member

airween commented Mar 6, 2025

Hi @Ablfantastic,

thanks for reporting this.

Could you explain some details about your environment? Eg. library version, etc... And please take a look at the issue template, where we ask these information:

...
**Server (please complete the following information):**
 - ModSecurity version (and connector): [e.g. ModSecurity v3.0.8 with nginx-connector v1.0.3]
 - WebServer: [e.g. nginx-1.18.0]
 - OS (and distro): [e.g. Linux, archlinux]

Anyway, I think this is important because I'm not able to reproduce your issue.

I checked the explained behavior with these rules:

SecRule REQUEST_BODY_LENGTH "@unconditionalMatch" "id:10001,phase:1,t:none,pass,log,msg:'%{MATCHED_VAR_NAME}: %{MATCHED_VAR}, phase: 1'"
SecRule REQUEST_BODY_LENGTH "@unconditionalMatch" "id:10002,phase:2,t:none,pass,log,msg:'%{MATCHED_VAR_NAME}: %{MATCHED_VAR}, phase: 2'"
SecRule REQUEST_BODY_LENGTH "@unconditionalMatch" "id:10003,phase:3,t:none,pass,log,msg:'%{MATCHED_VAR_NAME}: %{MATCHED_VAR}, phase: 3'"
SecRule REQUEST_BODY_LENGTH "@unconditionalMatch" "id:10004,phase:4,t:none,pass,log,msg:'%{MATCHED_VAR_NAME}: %{MATCHED_VAR}, phase: 4'"

and did that on mod_security2 and libmodsecurity3 (3.0.14) and Nginx (1.26.3) on Debian SID.

This is what I see in logs:

ModSecurity: Warning. Matched "Operator `UnconditionalMatch' with parameter `' against variable `REQUEST_BODY_LENGTH' (Value: `' ) [file "/home/airween/src/coreruleset/reqbodylen.conf"] [line "1"] [id "10001"] [rev ""] [msg "REQUEST_BODY_LENGTH: , phase: 1"] [data ""] ...
ModSecurity: Warning. Matched "Operator `UnconditionalMatch' with parameter `' against variable `REQUEST_BODY_LENGTH' (Value: `3' ) [file "/home/airween/src/coreruleset/reqbodylen.conf"] [line "2"] [id "10002"] [rev ""] [msg "REQUEST_BODY_LENGTH: 3, phase: 2"] [data ""] ...
ModSecurity: Warning. Matched "Operator `UnconditionalMatch' with parameter `' against variable `REQUEST_BODY_LENGTH' (Value: `3' ) [file "/home/airween/src/coreruleset/reqbodylen.conf"] [line "3"] [id "10003"] [rev ""] [msg "REQUEST_BODY_LENGTH: 3, phase: 3"] [data ""] ...

Just for the record: here are the lines from Apache's log:

ModSecurity: Warning. Unconditional match in SecAction. [file "/home/airween/src/coreruleset/reqbodylen.conf"] [line "1"] [id "10001"] [msg "REQUEST_BODY_LENGTH: 0, phase: 1"] ...
ModSecurity: Warning. Unconditional match in SecAction. [file "/home/airween/src/coreruleset/reqbodylen.conf"] [line "2"] [id "10002"] [msg "REQUEST_BODY_LENGTH: 3, phase: 2"] ...
ModSecurity: Warning. Unconditional match in SecAction. [file "/home/airween/src/coreruleset/reqbodylen.conf"] [line "3"] [id "10003"] [msg "REQUEST_BODY_LENGTH: 3, phase: 3"] ...
ModSecurity: Warning. Unconditional match in SecAction. [file "/home/airween/src/coreruleset/reqbodylen.conf"] [line "4"] [id "10004"] [msg "REQUEST_BODY_LENGTH: 3, phase: 4"] ...

As you can see, the value is available in phase:2 in both engines.

Set a rule that attempts to remove another rule based on REQUEST_BODY_LENGTH:

SecRule REQUEST_BODY_LENGTH "@gt 100" "id:10019,phase:1,nolog,pass,ctl:ruleRemoveById=200002"

Observe that REQUEST_BODY_LENGTH is only assigned a value in phase 3.

A rule like 200002 (executing in phase 2) cannot be dynamically removed based on body size, as the value is not available yet.

This issue is problematic for setups where large request bodies need to be conditionally exempt from strict ModSecurity enforcement. If REQUEST_BODY_LENGTH remains unavailable in phase 1 or 2, certain security mechanisms will always trigger before exclusions can be applied.

Yes, this would be a very problematic, if the mentioned variable appeared in phase:3.

But I think I see what's the problem here.

As I understand, you want to exclude rule 200002 if the REQUEST_BODY_LENGTH is greater than 100 bytes.
Rule 200002 is exists in modsecurity.conf, usually this file is processed first. Therefore the rule 200002 is activated in very early stage of phase:2 (this is the second rule in phase:2). Then later you want to remove this rule based on your condition. The necessary variable exists and available - the problem is not this. The problem is that you want to remove the rule AFTER that executed. And I assume therefore you think the variable isn't available yet in phase:2. And yes, in another rule which is in phase:3 you will see that value.

I assume the problem is this. Could you confirm it?

The solution could be if you add your exclusion before the rule that you want to exclude.

(I have to tell you I don't see the reason why do you want to ignore rule 200002 - you should explain that too, may be we can help to prevent a possible hole in your WAF)

@airween
Copy link
Member

airween commented Mar 10, 2025

@Ablfantastic any news? Could you check my suspicion above?

@Ablfantastic
Copy link
Author

I have updated the issue I mentioned above with the correct system specifications.

I wanted to ignore rule 200002 when the request body is valid but exceeds the SecRequestBodyLimit, such as when uploading a file to my website.

I will investigate the issue further and report back once I reach a more solid conclusion.

Thank you very much,

Abel

@Ablfantastic
Copy link
Author

Hi @airween,

I've used your solution to remove the rule in the cases where I needed it. Thank you for your feedback!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
3.x Related to ModSecurity version 3.x
Projects
None yet
Development

No branches or pull requests

2 participants