From 9c1f82bd9d11e0149031fe0ee4650bad013cdd78 Mon Sep 17 00:00:00 2001 From: Ervin Hegedus Date: Wed, 14 Aug 2024 23:05:02 +0200 Subject: [PATCH 01/21] feat: Check if multipart header contains any special characters --- rules/REQUEST-922-MULTIPART-ATTACK.conf | 23 ++++++++ .../REQUEST-922-MULTIPART-ATTACK/922130.yaml | 52 +++++++++++++++++++ 2 files changed, 75 insertions(+) create mode 100644 tests/regression/tests/REQUEST-922-MULTIPART-ATTACK/922130.yaml diff --git a/rules/REQUEST-922-MULTIPART-ATTACK.conf b/rules/REQUEST-922-MULTIPART-ATTACK.conf index 6663a1189..5b49c4bec 100644 --- a/rules/REQUEST-922-MULTIPART-ATTACK.conf +++ b/rules/REQUEST-922-MULTIPART-ATTACK.conf @@ -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. +# 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 [\x20-\x7E]" \ + "id:922130,\ + phase:2,\ + block,\ + capture,\ + t:none,t:lowercase,\ + msg:'Multipart header contains special characters which should not be used',\ + logdata:'Matched Data: %{TX.0}',\ + tag:'application-multi',\ + tag:'language-multi',\ + tag:'platform-multi',\ + tag:'attack-deprecated-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}'" + diff --git a/tests/regression/tests/REQUEST-922-MULTIPART-ATTACK/922130.yaml b/tests/regression/tests/REQUEST-922-MULTIPART-ATTACK/922130.yaml new file mode 100644 index 000000000..4e35b93ed --- /dev/null +++ b/tests/regression/tests/REQUEST-922-MULTIPART-ATTACK/922130.yaml @@ -0,0 +1,52 @@ +--- +meta: + author: "Ervin Hegedus" + description: Test Multipart/form-data +rule_id: 922130 +tests: + - test_id: 1 + desc: "Positive test: 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 + \u000eContent-Disposition: form-data; name="file"; filename="1.php" + + Date: Mon, 19 Aug 2024 22:19:38 +0200 Subject: [PATCH 02/21] Changed @rx behavior to positive match; Fix first test for both cases (engine detects this request or not) --- rules/REQUEST-922-MULTIPART-ATTACK.conf | 2 +- .../REQUEST-922-MULTIPART-ATTACK/922130.yaml | 15 ++------------- 2 files changed, 3 insertions(+), 14 deletions(-) diff --git a/rules/REQUEST-922-MULTIPART-ATTACK.conf b/rules/REQUEST-922-MULTIPART-ATTACK.conf index 5b49c4bec..25fc0c8ce 100644 --- a/rules/REQUEST-922-MULTIPART-ATTACK.conf +++ b/rules/REQUEST-922-MULTIPART-ATTACK.conf @@ -99,7 +99,7 @@ SecRule MULTIPART_PART_HEADERS "@rx content-transfer-encoding:(.*)" \ # Multipart header names can't contain any characters outside of range 33 and 126. # 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 [\x20-\x7E]" \ +SecRule MULTIPART_PART_HEADERS "@rx [^\x20-\x7E]" \ "id:922130,\ phase:2,\ block,\ diff --git a/tests/regression/tests/REQUEST-922-MULTIPART-ATTACK/922130.yaml b/tests/regression/tests/REQUEST-922-MULTIPART-ATTACK/922130.yaml index 4e35b93ed..28ea2df08 100644 --- a/tests/regression/tests/REQUEST-922-MULTIPART-ATTACK/922130.yaml +++ b/tests/regression/tests/REQUEST-922-MULTIPART-ATTACK/922130.yaml @@ -9,24 +9,13 @@ tests: 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 - \u000eContent-Disposition: form-data; name="file"; filename="1.php" - - Date: Mon, 19 Aug 2024 23:27:30 +0200 Subject: [PATCH 03/21] Fix yaml regex syntax --- tests/regression/tests/REQUEST-922-MULTIPART-ATTACK/922130.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/regression/tests/REQUEST-922-MULTIPART-ATTACK/922130.yaml b/tests/regression/tests/REQUEST-922-MULTIPART-ATTACK/922130.yaml index 28ea2df08..eff337522 100644 --- a/tests/regression/tests/REQUEST-922-MULTIPART-ATTACK/922130.yaml +++ b/tests/regression/tests/REQUEST-922-MULTIPART-ATTACK/922130.yaml @@ -15,7 +15,7 @@ tests: encoded_request: "UE9TVCAvcG9zdCBIVFRQLzEuMQ0KQWNjZXB0OiAqLyoNCkNvbm5lY3Rpb246IGNsb3NlDQpDb250ZW50LUxlbmd0aDogMTg1DQpDb250ZW50LVR5cGU6IG11bHRpcGFydC9mb3JtLWRhdGE7IGJvdW5kYXJ5PWJvdW5kYXJ5DQpIb3N0OiBsb2NhbGhvc3QNClVzZXItQWdlbnQ6IE9XQVNQIENSUyB0ZXN0IGFnZW50DQoNCi0tYm91bmRhcnkNCg5Db250ZW50LURpc3Bvc2l0aW9uOiBmb3JtLWRhdGE7IG5hbWU9ImZpbGUiOyBmaWxlbmFtZT0iMS5waHAiDQpDb250ZW50LURpc3Bvc2l0aW9uOiBmb3JtLWRhdGE7IG5hbWU9InBvc3QiDQoNCjxwaHAgdmFyX2R1bXAoZmlsZV9nZXRfY29udGVudHMoIi9ldGMvcGFzc3dkIikpOw0KLS1ib3VuZGFyeS0t" output: log: - match_regex: "Multipart parsing error: Multipart: Invalid part header \(contains invalid character\)|\[id \"922130\"\] \[msg \"Multipart header contains special characters which should not be used\"\]" + match_regex: 'Multipart parsing error: Multipart: Invalid part header (contains invalid character)|[id "922130"] [msg "Multipart header contains special characters which should not be used"]' - test_id: 2 desc: "Negative test: no special character in multipart header" stages: From ca22ef07d0cc7b3dacf0a1e173a7235baf160fdc Mon Sep 17 00:00:00 2001 From: Ervin Hegedus Date: Mon, 19 Aug 2024 23:47:37 +0200 Subject: [PATCH 04/21] Change tag 'deprecated' to 'multipart' MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Felipe Zipitría <3012076+fzipi@users.noreply.github.com> --- rules/REQUEST-922-MULTIPART-ATTACK.conf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rules/REQUEST-922-MULTIPART-ATTACK.conf b/rules/REQUEST-922-MULTIPART-ATTACK.conf index 25fc0c8ce..2b427f534 100644 --- a/rules/REQUEST-922-MULTIPART-ATTACK.conf +++ b/rules/REQUEST-922-MULTIPART-ATTACK.conf @@ -110,7 +110,7 @@ SecRule MULTIPART_PART_HEADERS "@rx [^\x20-\x7E]" \ tag:'application-multi',\ tag:'language-multi',\ tag:'platform-multi',\ - tag:'attack-deprecated-header',\ + tag:'attack-multipart-header',\ tag:'paranoia-level/1',\ tag:'OWASP_CRS',\ tag:'capec/272/220',\ From 4b3ee5710c51d67edbbb2a5b3ada3e406a807d6e Mon Sep 17 00:00:00 2001 From: Ervin Hegedus Date: Mon, 19 Aug 2024 23:48:58 +0200 Subject: [PATCH 05/21] Added '?' after '<' for the correct PHP open tag MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Felipe Zipitría <3012076+fzipi@users.noreply.github.com> --- tests/regression/tests/REQUEST-922-MULTIPART-ATTACK/922130.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/regression/tests/REQUEST-922-MULTIPART-ATTACK/922130.yaml b/tests/regression/tests/REQUEST-922-MULTIPART-ATTACK/922130.yaml index eff337522..c14192ab0 100644 --- a/tests/regression/tests/REQUEST-922-MULTIPART-ATTACK/922130.yaml +++ b/tests/regression/tests/REQUEST-922-MULTIPART-ATTACK/922130.yaml @@ -34,7 +34,7 @@ tests: --boundary Content-Disposition: form-data; name="file"; filename="1.php" - --boundary-- output: log: From ca708c897742d19da96f5140371b4ff63c8e389a Mon Sep 17 00:00:00 2001 From: Ervin Hegedus Date: Tue, 20 Aug 2024 16:08:59 +0200 Subject: [PATCH 06/21] Added '?' after '<' for the correct PHP open tag for positive test --- tests/regression/tests/REQUEST-922-MULTIPART-ATTACK/922130.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/regression/tests/REQUEST-922-MULTIPART-ATTACK/922130.yaml b/tests/regression/tests/REQUEST-922-MULTIPART-ATTACK/922130.yaml index c14192ab0..412c0238f 100644 --- a/tests/regression/tests/REQUEST-922-MULTIPART-ATTACK/922130.yaml +++ b/tests/regression/tests/REQUEST-922-MULTIPART-ATTACK/922130.yaml @@ -12,7 +12,7 @@ tests: port: 80 uri: "/post" version: "HTTP/1.1" - encoded_request: "UE9TVCAvcG9zdCBIVFRQLzEuMQ0KQWNjZXB0OiAqLyoNCkNvbm5lY3Rpb246IGNsb3NlDQpDb250ZW50LUxlbmd0aDogMTg1DQpDb250ZW50LVR5cGU6IG11bHRpcGFydC9mb3JtLWRhdGE7IGJvdW5kYXJ5PWJvdW5kYXJ5DQpIb3N0OiBsb2NhbGhvc3QNClVzZXItQWdlbnQ6IE9XQVNQIENSUyB0ZXN0IGFnZW50DQoNCi0tYm91bmRhcnkNCg5Db250ZW50LURpc3Bvc2l0aW9uOiBmb3JtLWRhdGE7IG5hbWU9ImZpbGUiOyBmaWxlbmFtZT0iMS5waHAiDQpDb250ZW50LURpc3Bvc2l0aW9uOiBmb3JtLWRhdGE7IG5hbWU9InBvc3QiDQoNCjxwaHAgdmFyX2R1bXAoZmlsZV9nZXRfY29udGVudHMoIi9ldGMvcGFzc3dkIikpOw0KLS1ib3VuZGFyeS0t" + encoded_request: "UE9TVCAvcG9zdCBIVFRQLzEuMQ0KQWNjZXB0OiAqLyoNCkNvbm5lY3Rpb246IGNsb3NlDQpDb250ZW50LUxlbmd0aDogMTg2DQpDb250ZW50LVR5cGU6IG11bHRpcGFydC9mb3JtLWRhdGE7IGJvdW5kYXJ5PWJvdW5kYXJ5DQpIb3N0OiBsb2NhbGhvc3QNClVzZXItQWdlbnQ6IE9XQVNQIENSUyB0ZXN0IGFnZW50DQoNCi0tYm91bmRhcnkNCg5Db250ZW50LURpc3Bvc2l0aW9uOiBmb3JtLWRhdGE7IG5hbWU9ImZpbGUiOyBmaWxlbmFtZT0iMS5waHAiDQpDb250ZW50LURpc3Bvc2l0aW9uOiBmb3JtLWRhdGE7IG5hbWU9InBvc3QiDQoNCjw/cGhwIHZhcl9kdW1wKGZpbGVfZ2V0X2NvbnRlbnRzKCIvZXRjL3Bhc3N3ZCIpKTsNCi0tYm91bmRhcnktLQ==" output: log: match_regex: 'Multipart parsing error: Multipart: Invalid part header (contains invalid character)|[id "922130"] [msg "Multipart header contains special characters which should not be used"]' From 1f67a91f9a699971c518531e3cfe475b4fcdaabf Mon Sep 17 00:00:00 2001 From: Ervin Hegedus Date: Tue, 20 Aug 2024 16:12:25 +0200 Subject: [PATCH 07/21] Added '\' sequence to avoid building regex --- tests/regression/tests/REQUEST-922-MULTIPART-ATTACK/922130.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/regression/tests/REQUEST-922-MULTIPART-ATTACK/922130.yaml b/tests/regression/tests/REQUEST-922-MULTIPART-ATTACK/922130.yaml index 412c0238f..55470f125 100644 --- a/tests/regression/tests/REQUEST-922-MULTIPART-ATTACK/922130.yaml +++ b/tests/regression/tests/REQUEST-922-MULTIPART-ATTACK/922130.yaml @@ -15,7 +15,7 @@ tests: encoded_request: "UE9TVCAvcG9zdCBIVFRQLzEuMQ0KQWNjZXB0OiAqLyoNCkNvbm5lY3Rpb246IGNsb3NlDQpDb250ZW50LUxlbmd0aDogMTg2DQpDb250ZW50LVR5cGU6IG11bHRpcGFydC9mb3JtLWRhdGE7IGJvdW5kYXJ5PWJvdW5kYXJ5DQpIb3N0OiBsb2NhbGhvc3QNClVzZXItQWdlbnQ6IE9XQVNQIENSUyB0ZXN0IGFnZW50DQoNCi0tYm91bmRhcnkNCg5Db250ZW50LURpc3Bvc2l0aW9uOiBmb3JtLWRhdGE7IG5hbWU9ImZpbGUiOyBmaWxlbmFtZT0iMS5waHAiDQpDb250ZW50LURpc3Bvc2l0aW9uOiBmb3JtLWRhdGE7IG5hbWU9InBvc3QiDQoNCjw/cGhwIHZhcl9kdW1wKGZpbGVfZ2V0X2NvbnRlbnRzKCIvZXRjL3Bhc3N3ZCIpKTsNCi0tYm91bmRhcnktLQ==" output: log: - match_regex: 'Multipart parsing error: Multipart: Invalid part header (contains invalid character)|[id "922130"] [msg "Multipart header contains special characters which should not be used"]' + match_regex: 'Multipart parsing error: Multipart: Invalid part header \(contains invalid character\)|\[id "922130"\] \[msg "Multipart header contains special characters which should not be used"\]' - test_id: 2 desc: "Negative test: no special character in multipart header" stages: From f9fe603c352435ae5b049db2f345a9db4b2b945d Mon Sep 17 00:00:00 2001 From: Ervin Hegedus Date: Tue, 20 Aug 2024 17:40:34 +0200 Subject: [PATCH 08/21] Replace expected output result to handle both situation --- tests/regression/tests/REQUEST-922-MULTIPART-ATTACK/922130.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/regression/tests/REQUEST-922-MULTIPART-ATTACK/922130.yaml b/tests/regression/tests/REQUEST-922-MULTIPART-ATTACK/922130.yaml index 55470f125..e0d332eb0 100644 --- a/tests/regression/tests/REQUEST-922-MULTIPART-ATTACK/922130.yaml +++ b/tests/regression/tests/REQUEST-922-MULTIPART-ATTACK/922130.yaml @@ -38,4 +38,4 @@ tests: --boundary-- output: log: - no_expect_ids: [922130] + no_match_regex: 'Multipart parsing error: Multipart: Invalid part header \(contains invalid character\)|\[id "922130"\] \[msg "Multipart header contains special characters which should not be used"\]' From ae740c647628cc3d4f37957e41138101f6562b4d Mon Sep 17 00:00:00 2001 From: Ervin Hegedus Date: Tue, 20 Aug 2024 17:44:28 +0200 Subject: [PATCH 09/21] Added explanation of expected results --- tests/regression/tests/REQUEST-922-MULTIPART-ATTACK/922130.yaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/regression/tests/REQUEST-922-MULTIPART-ATTACK/922130.yaml b/tests/regression/tests/REQUEST-922-MULTIPART-ATTACK/922130.yaml index e0d332eb0..5e9b9df98 100644 --- a/tests/regression/tests/REQUEST-922-MULTIPART-ATTACK/922130.yaml +++ b/tests/regression/tests/REQUEST-922-MULTIPART-ATTACK/922130.yaml @@ -15,6 +15,8 @@ tests: 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 special characters which should not be used"\]' - test_id: 2 desc: "Negative test: no special character in multipart header" From 122acdb5c6faeff622e316bd39fe3a466027193d Mon Sep 17 00:00:00 2001 From: Ervin Hegedus Date: Tue, 20 Aug 2024 17:50:26 +0200 Subject: [PATCH 10/21] Added a clarficiation about the encoded request --- .../tests/REQUEST-922-MULTIPART-ATTACK/922130.yaml | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/tests/regression/tests/REQUEST-922-MULTIPART-ATTACK/922130.yaml b/tests/regression/tests/REQUEST-922-MULTIPART-ATTACK/922130.yaml index 5e9b9df98..ed4a5092e 100644 --- a/tests/regression/tests/REQUEST-922-MULTIPART-ATTACK/922130.yaml +++ b/tests/regression/tests/REQUEST-922-MULTIPART-ATTACK/922130.yaml @@ -5,7 +5,16 @@ meta: rule_id: 922130 tests: - test_id: 1 - desc: "Positive test: special character in multipart header" + desc: | + # Positive test: special character in multipart header + # Request is a multipart request with 2 Content-Disposition header, + # where the first one contains a 0x0E character + # --boundary + # Content-Disposition: form-data; name="file"; filename="1.php" + # Content-Disposition: form-data; name="post" + # + # Date: Tue, 20 Aug 2024 22:09:48 +0200 Subject: [PATCH 11/21] Show special character in decoded MP header --- tests/regression/tests/REQUEST-922-MULTIPART-ATTACK/922130.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/regression/tests/REQUEST-922-MULTIPART-ATTACK/922130.yaml b/tests/regression/tests/REQUEST-922-MULTIPART-ATTACK/922130.yaml index ed4a5092e..f04c8b939 100644 --- a/tests/regression/tests/REQUEST-922-MULTIPART-ATTACK/922130.yaml +++ b/tests/regression/tests/REQUEST-922-MULTIPART-ATTACK/922130.yaml @@ -10,7 +10,7 @@ tests: # Request is a multipart request with 2 Content-Disposition header, # where the first one contains a 0x0E character # --boundary - # Content-Disposition: form-data; name="file"; filename="1.php" + # \x0EContent-Disposition: form-data; name="file"; filename="1.php" # Content-Disposition: form-data; name="post" # # Date: Wed, 21 Aug 2024 20:49:13 +0200 Subject: [PATCH 12/21] Fix character range --- rules/REQUEST-922-MULTIPART-ATTACK.conf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rules/REQUEST-922-MULTIPART-ATTACK.conf b/rules/REQUEST-922-MULTIPART-ATTACK.conf index 2b427f534..6b198a8de 100644 --- a/rules/REQUEST-922-MULTIPART-ATTACK.conf +++ b/rules/REQUEST-922-MULTIPART-ATTACK.conf @@ -99,7 +99,7 @@ SecRule MULTIPART_PART_HEADERS "@rx content-transfer-encoding:(.*)" \ # Multipart header names can't contain any characters outside of range 33 and 126. # 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 [^\x20-\x7E]" \ +SecRule MULTIPART_PART_HEADERS "@rx [^\x21-\x7E]" \ "id:922130,\ phase:2,\ block,\ From 903974c8cc84fd9bd67170e7f567b81998993b95 Mon Sep 17 00:00:00 2001 From: Ervin Hegedus Date: Wed, 21 Aug 2024 20:53:55 +0200 Subject: [PATCH 13/21] Remove # chars from the beginning of description lines --- .../REQUEST-922-MULTIPART-ATTACK/922130.yaml | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/tests/regression/tests/REQUEST-922-MULTIPART-ATTACK/922130.yaml b/tests/regression/tests/REQUEST-922-MULTIPART-ATTACK/922130.yaml index f04c8b939..d4f302acb 100644 --- a/tests/regression/tests/REQUEST-922-MULTIPART-ATTACK/922130.yaml +++ b/tests/regression/tests/REQUEST-922-MULTIPART-ATTACK/922130.yaml @@ -6,15 +6,14 @@ rule_id: 922130 tests: - test_id: 1 desc: | - # Positive test: special character in multipart header - # Request is a multipart request with 2 Content-Disposition header, - # where the first one contains a 0x0E character - # --boundary - # \x0EContent-Disposition: form-data; name="file"; filename="1.php" - # Content-Disposition: form-data; name="post" - # - # Date: Sun, 25 Aug 2024 19:01:41 +0200 Subject: [PATCH 14/21] Fixed regex to catch invalid header; added another test --- rules/REQUEST-922-MULTIPART-ATTACK.conf | 6 ++--- .../REQUEST-922-MULTIPART-ATTACK/922130.yaml | 26 ++++++++++++++++++- 2 files changed, 28 insertions(+), 4 deletions(-) diff --git a/rules/REQUEST-922-MULTIPART-ATTACK.conf b/rules/REQUEST-922-MULTIPART-ATTACK.conf index 6b198a8de..6a8a177b5 100644 --- a/rules/REQUEST-922-MULTIPART-ATTACK.conf +++ b/rules/REQUEST-922-MULTIPART-ATTACK.conf @@ -96,10 +96,11 @@ SecRule MULTIPART_PART_HEADERS "@rx content-transfer-encoding:(.*)" \ 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. +# 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]" \ +SecRule MULTIPART_PART_HEADERS "@rx [^\x21-\x7E][^:]*:" \ "id:922130,\ phase:2,\ block,\ @@ -117,4 +118,3 @@ SecRule MULTIPART_PART_HEADERS "@rx [^\x21-\x7E]" \ ver:'OWASP_CRS/4.6.0-dev',\ severity:'CRITICAL',\ setvar:'tx.inbound_anomaly_score_pl1=+%{tx.critical_anomaly_score}'" - diff --git a/tests/regression/tests/REQUEST-922-MULTIPART-ATTACK/922130.yaml b/tests/regression/tests/REQUEST-922-MULTIPART-ATTACK/922130.yaml index d4f302acb..68b2cb59d 100644 --- a/tests/regression/tests/REQUEST-922-MULTIPART-ATTACK/922130.yaml +++ b/tests/regression/tests/REQUEST-922-MULTIPART-ATTACK/922130.yaml @@ -12,7 +12,8 @@ tests: --boundary \x0EContent-Disposition: form-data; name="file"; filename="1.php" Content-Disposition: form-data; name="post" - # Date: Sun, 25 Aug 2024 20:41:34 +0200 Subject: [PATCH 15/21] Improving regex --- rules/REQUEST-922-MULTIPART-ATTACK.conf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rules/REQUEST-922-MULTIPART-ATTACK.conf b/rules/REQUEST-922-MULTIPART-ATTACK.conf index 6a8a177b5..bc3b27f2a 100644 --- a/rules/REQUEST-922-MULTIPART-ATTACK.conf +++ b/rules/REQUEST-922-MULTIPART-ATTACK.conf @@ -100,7 +100,7 @@ SecRule MULTIPART_PART_HEADERS "@rx content-transfer-encoding:(.*)" \ # 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][^:]*:" \ +SecRule MULTIPART_PART_HEADERS "@rx [^\x21-\x7E][\x21-\x39\x3B-\x7E]*:" \ "id:922130,\ phase:2,\ block,\ From 2d89377d97cc918c9f6faf2b3624c2874b025506 Mon Sep 17 00:00:00 2001 From: Ervin Hegedus Date: Sun, 25 Aug 2024 20:42:43 +0200 Subject: [PATCH 16/21] Added tests to check regex range boundaries --- .../REQUEST-922-MULTIPART-ATTACK/922130.yaml | 94 +++++++++++++++++++ 1 file changed, 94 insertions(+) diff --git a/tests/regression/tests/REQUEST-922-MULTIPART-ATTACK/922130.yaml b/tests/regression/tests/REQUEST-922-MULTIPART-ATTACK/922130.yaml index 68b2cb59d..56e4553f3 100644 --- a/tests/regression/tests/REQUEST-922-MULTIPART-ATTACK/922130.yaml +++ b/tests/regression/tests/REQUEST-922-MULTIPART-ATTACK/922130.yaml @@ -73,3 +73,97 @@ tests: output: log: no_match_regex: 'Multipart parsing error: Multipart: Invalid part header \(contains invalid character\)|\[id "922130"\] \[msg "Multipart header contains special characters which should not be used"\]' + - test_id: 4 + desc: | + Positive test: special character in multipart header + Request is a multipart request with 2 Content-Disposition header, + where the first one contains a 0x0E character + --boundary + Content-\x20Disposition: form-data; name="file"; filename="1.php" + Content-Disposition: form-data; name="post" + + + --boundary-- + output: + log: + no_match_regex: 'Multipart parsing error: Multipart: Invalid part header \(contains invalid character\)|\[id "922130"\] \[msg "Multipart header contains special characters which should not be used"\]' + - test_id: 6 + desc: "Negative test: no character from outside of range in multipart header; '~' is allowed (\x7E)" + 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" + + + --boundary-- + output: + log: + no_match_regex: 'Multipart parsing error: Multipart: Invalid part header \(contains invalid character\)|\[id "922130"\] \[msg "Multipart header contains special characters which should not be used"\]' + - test_id: 7 + desc: | + Positive test: special character in multipart header + Request is a multipart request with 2 Content-Disposition header, + where the first one contains a 0x0E character + --boundary + Content~Disposition: form-data; name="file"; filename="1.php" + Content-Disposition: form-data; name="post" + + Date: Sun, 25 Aug 2024 21:34:29 +0200 Subject: [PATCH 17/21] Message clarification --- rules/REQUEST-922-MULTIPART-ATTACK.conf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rules/REQUEST-922-MULTIPART-ATTACK.conf b/rules/REQUEST-922-MULTIPART-ATTACK.conf index bc3b27f2a..6ea38ede1 100644 --- a/rules/REQUEST-922-MULTIPART-ATTACK.conf +++ b/rules/REQUEST-922-MULTIPART-ATTACK.conf @@ -106,7 +106,7 @@ SecRule MULTIPART_PART_HEADERS "@rx [^\x21-\x7E][\x21-\x39\x3B-\x7E]*:" \ block,\ capture,\ t:none,t:lowercase,\ - msg:'Multipart header contains special characters which should not be used',\ + msg:'Multipart header contains characters outside of valid range',\ logdata:'Matched Data: %{TX.0}',\ tag:'application-multi',\ tag:'language-multi',\ From f011d6f39133658ea697591e1f3e491b158a1a61 Mon Sep 17 00:00:00 2001 From: Ervin Hegedus Date: Sun, 25 Aug 2024 21:41:52 +0200 Subject: [PATCH 18/21] Fix yamllint issue, typos, align new 'msg' content --- .../REQUEST-922-MULTIPART-ATTACK/922130.yaml | 35 +++++++++---------- 1 file changed, 17 insertions(+), 18 deletions(-) diff --git a/tests/regression/tests/REQUEST-922-MULTIPART-ATTACK/922130.yaml b/tests/regression/tests/REQUEST-922-MULTIPART-ATTACK/922130.yaml index 56e4553f3..d41895535 100644 --- a/tests/regression/tests/REQUEST-922-MULTIPART-ATTACK/922130.yaml +++ b/tests/regression/tests/REQUEST-922-MULTIPART-ATTACK/922130.yaml @@ -6,8 +6,8 @@ rule_id: 922130 tests: - test_id: 1 desc: | - Positive test: special character in multipart header - Request is a multipart request with 2 Content-Disposition header, + 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 --boundary \x0EContent-Disposition: form-data; name="file"; filename="1.php" @@ -26,11 +26,11 @@ tests: 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 special characters which should not be used"\]' + 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 header, + 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 --boundary Content-Disposition\x0E: form-data; name="file"; filename="1.php" @@ -49,7 +49,7 @@ tests: 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 special characters which should not be used"\]' + 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: @@ -72,11 +72,11 @@ tests: --boundary-- output: log: - no_match_regex: 'Multipart parsing error: Multipart: Invalid part header \(contains invalid character\)|\[id "922130"\] \[msg "Multipart header contains special characters which should not be used"\]' + 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 header, + 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 --boundary Content-\x20Disposition: form-data; name="file"; filename="1.php" @@ -95,7 +95,7 @@ tests: 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 special characters which should not be used"\]' + 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)" stages: @@ -118,7 +118,7 @@ tests: --boundary-- output: log: - no_match_regex: 'Multipart parsing error: Multipart: Invalid part header \(contains invalid character\)|\[id "922130"\] \[msg "Multipart header contains special characters which should not be used"\]' + 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)" stages: @@ -142,14 +142,14 @@ tests: --boundary-- output: log: - no_match_regex: 'Multipart parsing error: Multipart: Invalid part header \(contains invalid character\)|\[id "922130"\] \[msg "Multipart header contains special characters which should not be used"\]' + 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 header, - where the first one contains a 0x0E character + 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~Disposition: form-data; name="file"; filename="1.php" + Content\x7F-Disposition: form-data; name="file"; filename="1.php" Content-Disposition: form-data; name="post" Date: Sun, 25 Aug 2024 21:47:12 +0200 Subject: [PATCH 19/21] Typo fixes --- .../tests/REQUEST-922-MULTIPART-ATTACK/922130.yaml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/tests/regression/tests/REQUEST-922-MULTIPART-ATTACK/922130.yaml b/tests/regression/tests/REQUEST-922-MULTIPART-ATTACK/922130.yaml index d41895535..d3d47203b 100644 --- a/tests/regression/tests/REQUEST-922-MULTIPART-ATTACK/922130.yaml +++ b/tests/regression/tests/REQUEST-922-MULTIPART-ATTACK/922130.yaml @@ -8,7 +8,7 @@ tests: 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 + 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" @@ -77,7 +77,7 @@ tests: 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 + where the first one contains a 0x0E 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" @@ -97,7 +97,7 @@ tests: # 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)" + desc: "Negative test: no character from outside of range in multipart header; '!' is allowed (\x21, the first character of the range of valid characters))" stages: - input: dest_addr: 127.0.0.1 @@ -120,7 +120,7 @@ tests: 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)" + 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 @@ -135,7 +135,7 @@ tests: version: "HTTP/1.1" data: | --boundary - Content-!Disposition: form-data; name="file"; filename="1.php" + Content~Disposition: form-data; name="file"; filename="1.php" Content-Disposition: form-data; name="post" From 9c84a74bc89589653dee9a25da15f62aa2adf554 Mon Sep 17 00:00:00 2001 From: Ervin Hegedus Date: Sun, 25 Aug 2024 21:49:19 +0200 Subject: [PATCH 20/21] Description clarification --- tests/regression/tests/REQUEST-922-MULTIPART-ATTACK/922130.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/regression/tests/REQUEST-922-MULTIPART-ATTACK/922130.yaml b/tests/regression/tests/REQUEST-922-MULTIPART-ATTACK/922130.yaml index d3d47203b..cafd07b5c 100644 --- a/tests/regression/tests/REQUEST-922-MULTIPART-ATTACK/922130.yaml +++ b/tests/regression/tests/REQUEST-922-MULTIPART-ATTACK/922130.yaml @@ -31,7 +31,7 @@ tests: 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 + 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" From f4aedba9b1591d4e649a9bf4db092cc346938075 Mon Sep 17 00:00:00 2001 From: Ervin Hegedus Date: Mon, 26 Aug 2024 11:54:18 +0200 Subject: [PATCH 21/21] Typo fixes --- .../regression/tests/REQUEST-922-MULTIPART-ATTACK/922130.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/regression/tests/REQUEST-922-MULTIPART-ATTACK/922130.yaml b/tests/regression/tests/REQUEST-922-MULTIPART-ATTACK/922130.yaml index cafd07b5c..c733fecba 100644 --- a/tests/regression/tests/REQUEST-922-MULTIPART-ATTACK/922130.yaml +++ b/tests/regression/tests/REQUEST-922-MULTIPART-ATTACK/922130.yaml @@ -77,7 +77,7 @@ tests: 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, the last invalid character before the valid range. + 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" @@ -97,7 +97,7 @@ tests: # 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 of the range of valid characters))" + 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