8000 feat: add new rule to catch invalid character in multipart headers by airween · Pull Request #3796 · coreruleset/coreruleset · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

feat: add new rule to catch invalid character in multipart headers #3796

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

Merged
merged 24 commits into from
Aug 26, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
9c1f82b
feat: Check if multipart header contains any special characters
airween Aug 14, 2024
5dedb7a
Changed @rx behavior to positive match; Fix first test for both cases…
airween Aug 19, 2024
47c4c13
Fix yaml regex syntax
airween Aug 19, 2024
bb6e137
Merge branch 'main' into v4/mpheadercheck
airween Aug 19, 2024
ca22ef0
Change tag 'deprecated' to 'multipart'
airween Aug 19, 2024
4b3ee57
Added '?' after '<' for the correct PHP open tag
airween Aug 19, 2024
ca708c8
Added '?' after '<' for the correct PHP open tag for positive test
airween Aug 20, 2024
1f67a91
Added '\' sequence to avoid building regex
airween Aug 20, 2024
f9fe603
Replace expected output result to handle both situation
airween Aug 20, 2024
ae740c6
Added explanation of expected results
airween Aug 20, 2024
122acdb
Added a clarficiation about the encoded request
airween Aug 20, 2024
f32c242
Show special character in decoded MP header
airween Aug 20, 2024
f377c6a
Fix character range
airween Aug 21, 2024
903974c
Remove # chars from the beginning of description lines
airween Aug 21, 2024
f7089a2
Fixed regex to catch invalid header; added another test
airween Aug 25, 2024
ff1244b
Merge branch 'main' into v4/mpheadercheck
airween Aug 25, 2024
2cf3e08
Improving regex
airween Aug 25, 2024
2d89377
Added tests to check regex range boundaries
airween Aug 25, 2024
3703f63
Message clarification
airween Aug 25, 2024
f011d6f
Fix yamllint issue, typos, align new 'msg' content
airween Aug 25, 2024
7f34b75
Typo fixes
airween Aug 25, 2024
9c84a74
Description clarification
airween Aug 25, 2024
b7f882c
Merge branch 'main' into v4/mpheadercheck
fzipi Aug 25, 2024
f4aedba
Typo fixes
airween Aug 26, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 23 additions & 0 deletions rules/REQUEST-922-MULTIPART-ATTACK.conf
Original file line number Diff line number Diff line change
Expand Up @@ -95,3 +95,26 @@ SecRule MULTIPART_PART_HEADERS "@rx content-transfer-encoding:(.*)" \
ver:'OWASP_CRS/4.6.0-dev',\
severity:'CRITICAL',\
setvar:'tx.inbound_anomaly_score_pl1=+%{tx.critical_anomaly_score}'"

# Multipart header names can't contain any characters outside of range 33 and 126,
# excluding 58 (':') which is the separator.
# RFC 2045 refers RFC 822 about the header syntax.
# Note: this is in phase:2 because these are headers that come in the body
SecRule MULTIPART_PART_HEADERS "@rx [^\x21-\x7E][\x21-\x39\x3B-\x7E]*:" \
"id:922130,\
phase:2,\
block,\
capture,\
t:none,t:lowercase,\
msg:'Multipart header contains characters outside of valid range',\
logdata:'Matched Data: %{TX.0}',\
tag:'application-multi',\
tag:'language-multi',\
tag:'platform-multi',\
tag:'attack-multipart-header',\
tag:'paranoia-level/1',\
tag:'OWASP_CRS',\
tag:'capec/272/220',\
ver:'OWASP_CRS/4.6.0-dev',\
severity:'CRITICAL',\
setvar:'tx.inbound_anomaly_score_pl1=+%{tx.critical_anomaly_score}'"
168 changes: 168 additions & 0 deletions tests/regression/tests/REQUEST-922-MULTIPART-ATTACK/922130.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,168 @@
---
meta:
author: "Ervin Hegedus"
description: Test Multipart/form-data
rule_id: 922130
tests:
- test_id: 1
desc: |
Positive test: special character in multipart header.
Request is a multipart request with 2 Content-Disposition headers,
where the first one contains a 0x0E character at the first position.
--boundary
\x0EContent-Disposition: form-data; name="file"; filename="1.php"
Content-Disposition: form-data; name="post"

<?php var_dump(file_get_contents("/etc/passwd"));
--boundary--
stages:
- input:
dest_addr: 127.0.0.1
port: 80
uri: "/post"
version: "HTTP/1.1"
encoded_request: "UE9TVCAvcG9zdCBIVFRQLzEuMQ0KQWNjZXB0OiAqLyoNCkNvbm5lY3Rpb246IGNsb3NlDQpDb250ZW50LUxlbmd0aDogMTg2DQpDb250ZW50LVR5cGU6IG11bHRpcGFydC9mb3JtLWRhdGE7IGJvdW5kYXJ5PWJvdW5kYXJ5DQpIb3N0OiBsb2NhbGhvc3QNClVzZXItQWdlbnQ6IE9XQVNQIENSUyB0ZXN0IGFnZW50DQoNCi0tYm91bmRhcnkNCg5Db250ZW50LURpc3Bvc2l0aW9uOiBmb3JtLWRhdGE7IG5hbWU9ImZpbGUiOyBmaWxlbmFtZT0iMS5waHAiDQpDb250ZW50LURpc3Bvc2l0aW9uOiBmb3JtLWRhdGE7IG5hbWU9InBvc3QiDQoNCjw/cGhwIHZhcl9kdW1wKGZpbGVfZ2V0X2NvbnRlbnRzKCIvZXRjL3Bhc3N3ZCIpKTsNCi0tYm91bmRhcnktLQ=="
output:
log:
# The rule will match when an older version of the engine doesn't fail parsing. In newer versions of the engine,
# parsing will fail and the body will be considered invalid.
match_regex: 'Multipart parsing error: Multipart: Invalid part header \(contains invalid character\)|\[id "922130"\] \[msg "Multipart header contains characters outside of valid range"\]'
- test_id: 2
desc: |
Positive test: special character in multipart header.
Request is a multipart request with 2 Content-Disposition headers,
where the first one contains a 0x0E character at the last position.
--boundary
Content-Disposition\x0E: form-data; name="file"; filename="1.php"
Content-Disposition: form-data; name="post"

<?php var_dump(file_get_contents("/etc/passwd"));
--boundary--
stages:
- input:
dest_addr: 127.0.0.1
port: 80
uri: "/post"
version: "HTTP/1.1"
encoded_request: "UE9TVCAvcG9zdCBIVFRQLzEuMQ0KQWNjZXB0OiAqLyoNCkNvbm5lY3Rpb246IGNsb3NlDQpDb250ZW50LUxlbmd0aDogMTg2DQpDb250ZW50LVR5cGU6IG11bHRpcGFydC9mb3JtLWRhdGE7IGJvdW5kYXJ5PWJvdW5kYXJ5DQpIb3N0OiBsb2NhbGhvc3QNClVzZXItQWdlbnQ6IE9XQVNQIENSUyB0ZXN0IGFnZW50DQoNCi0tYm91bmRhcnkNCkNvbnRlbnQtRGlzcG9zaXRpb24OOiBmb3JtLWRhdGE7IG5hbWU9ImZpbGUiOyBmaWxlbmFtZT0iMS5waHAiDQpDb250ZW50LURpc3Bvc2l0aW9uOiBmb3JtLWRhdGE7IG5hbWU9InBvc3QiDQoNCjw/cGhwIHZhcl9kdW1wKGZpbGVfZ2V0X2NvbnRlbnRzKCIvZXRjL3Bhc3N3ZCIpKTsNCi0tYm91bmRhcnktLQ=="
output:
log:
# The rule will match when an older version of the engine doesn't fail parsing. In newer versions of the engine,
# parsing will fail and the body will be considered invalid.
match_regex: 'Multipart parsing error: Multipart: Invalid part header \(contains invalid character\)|\[id "922130"\] \[msg "Multipart header contains characters outside of valid range"\]'
- test_id: 3
desc: "Negative test: no special character in multipart header"
stages:
- input:
dest_addr: 127.0.0.1
headers:
Host: "localhost"
User-Agent: "OWASP CRS test agent"
Content-Type: multipart/form-data; boundary=boundary
Accept: "*/*"
method: POST
port: 80
uri: "/post"
version: "HTTP/1.1"
data: |
--boundary
Content-Disposition: form-data; name="file"; filename="1.php"

<?php var_dump(file_get_contents("/etc/passwd")); ?>
--boundary--
output:
log:
no_match_regex: 'Multipart parsing error: Multipart: Invalid part header \(contains invalid character\)|\[id "922130"\] \[msg "Multipart header contains characters outside of valid range"\]'
- test_id: 4
desc: |
Positive test: special character in multipart header.
Request is a multipart request with 2 Content-Disposition headers,
where the first one contains a 0x20 character, the last invalid character before the valid range.
--boundary
Content-\x20Disposition: form-data; name="file"; filename="1.php"
Content-Disposition: form-data; name="post"

<?php var_dump(file_get_contents("/etc/passwd"));
--boundary--
stages:
- input:
dest_addr: 127.0.0.1
port: 80
uri: "/post"
version: "HTTP/1.1"
encoded_request: "UE9TVCAvcG9zdCBIVFRQLzEuMQ0KQWNjZXB0OiAqLyoNCkNvbm5lY3Rpb246IGNsb3NlDQpDb250ZW50LUxlbmd0aDogMTg2DQpDb250ZW50LVR5cGU6IG11bHRpcGFydC9mb3JtLWRhdGE7IGJvdW5kYXJ5PWJvdW5kYXJ5DQpIb3N0OiBsb2NhbGhvc3QNClVzZXItQWdlbnQ6IE9XQVNQIENSUyB0ZXN0IGFnZW50DQoNCi0tYm91bmRhcnkNCkNvbnRlbnQtIERpc3Bvc2l0aW9uOiBmb3JtLWRhdGE7IG5hbWU9ImZpbGUiOyBmaWxlbmFtZT0iMS5waHAiDQpDb250ZW50LURpc3Bvc2l0aW9uOiBmb3JtLWRhdGE7IG5hbWU9InBvc3QiDQoNCjw/cGhwIHZhcl9kdW1wKGZpbGVfZ2V0X2NvbnRlbnRzKCIvZXRjL3Bhc3N3ZCIpKTsNCi0tYm91bmRhcnktLQ=="
output:
log:
# The rule will match when an older version of the engine doesn't fail parsing. In newer versions of the engine,
# parsing will fail and the body will be considered invalid.
match_regex: 'Multipart parsing error: Multipart: Invalid part header \(contains invalid character\)|\[id "922130"\] \[msg "Multipart header contains characters outside of valid range"\]'
- test_id: 5
desc: "Negative test: no character from outside of range in multipart header; '!' is allowed (\x21, the first character in the range of valid characters))"
stages:
- input:
dest_addr: 127.0.0.1
headers:
Host: "localhost"
User-Agent: "OWASP CRS test agent"
Content-Type: multipart/form-data; boundary=boundary
Accept: "*/*"
method: POST
port: 80
uri: "/post"
version: "HTTP/1.1"
data: |
--boundary
Content-!Disposition: form-data; name="file"; filename="1.php"

<?php var_dump(file_get_contents("/etc/passwd")); ?>
--boundary--
output:
log:
no_match_regex: 'Multipart parsing error: Multipart: Invalid part header \(contains invalid character\)|\[id "922130"\] \[msg "Multipart header contains characters outside of valid range"\]'
- test_id: 6
desc: "Negative test: no character from outside of range in multipart header; '~' is allowed (\x7E, the last valid character in the range of valid characters)"
stages:
- input:
dest_addr: 127.0.0.1
headers:
Host: "localhost"
User-Agent: "OWASP CRS test agent"
Content-Type: multipart/form-data; boundary=boundary
Accept: "*/*"
method: POST
port: 80
uri: "/post"
version: "HTTP/1.1"
data: |
--boundary
Content~Disposition: form-data; name="file"; filename="1.php"
Content-Disposition: form-data; name="post"

<?php var_dump(file_get_contents("/etc/passwd")); ?>
--boundary--
output:
log:
no_match_regex: 'Multipart parsing error: Multipart: Invalid part header \(contains invalid character\)|\[id "922130"\] \[msg "Multipart header contains characters outside of valid range"\]'
- test_id: 7
desc: |
Positive test: special character in multipart header.
Request is a multipart request with 2 Content-Disposition headers,
where the first one contains a 0x7F character, the first invalid character after the valid range.
--boundary
Content\x7F-Disposition: form-data; name="file"; filename="1.php"
Content-Disposition: form-data; name="post"

<?php var_dump(file_get_contents("/etc/passwd"));
--boundary--
stages:
- input:
dest_addr: 127.0.0.1
port: 80
uri: "/post"
version: "HTTP/1.1"
encoded_request: "UE9TVCAvcG9zdCBIVFRQLzEuMQ0KQWNjZXB0OiAqLyoNCkNvbm5lY3Rpb246IGNsb3NlDQpDb250ZW50LUxlbmd0aDogMTg2DQpDb250ZW50LVR5cGU6IG11bHRpcGFydC9mb3JtLWRhdGE7IGJvdW5kYXJ5PWJvdW5kYXJ5DQpIb3N0OiBsb2NhbGhvc3QNClVzZXItQWdlbnQ6IE9XQVNQIENSUyB0ZXN0IGFnZW50DQoNCi0tYm91bmRhcnkNCkNvbnRlbnR/LURpc3Bvc2l0aW9uOiBmb3JtLWRhdGE7IG5hbWU9ImZpbGUiOyBmaWxlbmFtZT0iMS5waHAiDQpDb250ZW50LURpc3Bvc2l0aW9uOiBmb3JtLWRhdGE7IG5hbWU9InBvc3QiDQoNCjw/cGhwIHZhcl9kdW1wKGZpbGVfZ2V0X2NvbnRlbnRzKCIvZXRjL3Bhc3N3ZCIpKTsNCi0tYm91bmRhcnktLQ=="
output:
log:
# The rule will match when an older version of the engine doesn't fail parsing. In newer versions of the engine,
# parsing will fail and the body will be considered invalid.
match_regex: 'Multipart parsing error: Multipart: Invalid part header \(contains invalid character\)|\[id "922130"\] \[msg "Multipart header contains characters outside of valid range"\]'
0