rubygem-puma/CVE-2021-41136.patch
2023-12-20 10:01:15 +08:00

253 lines
12 KiB
Diff

From acdc3ae571dfae0e045cf09a295280127db65c7f Mon Sep 17 00:00:00 2001
From: Nate Berkopec <nate.berkopec@gmail.com>
Date: Tue, 12 Oct 2021 08:38:40 -0600
Subject: [PATCH] Merge pull request from GHSA-48w2-rm65-62xx
* Fix HTTP request smuggling vulnerability
See GHSA-48w2-rm65-62xx or CVE-2021-41136 for more info.
* 4.3.9 release note
* 5.5.1 release note
* 5.5.1
---
ext/puma_http11/http11_parser.c | 17 +++-
ext/puma_http11/http11_parser_common.rl | 2 +-
.../org/jruby/puma/Http11Parser.java | 92 +++++++++----------
test/test_http11.rb | 30 ++++++
4 files changed, 88 insertions(+), 53 deletions(-)
diff --git a/ext/puma_http11/http11_parser.c b/ext/puma_http11/http11_parser.c
index e8844a3..be40555 100644
--- a/ext/puma_http11/http11_parser.c
+++ b/ext/puma_http11/http11_parser.c
@@ -428,10 +428,13 @@ st18:
case 18:
#line 428 "ext/puma_http11/http11_parser.c"
switch( (*p) ) {
+ case 9: goto tr25;
case 13: goto tr26;
case 32: goto tr27;
}
- goto tr25;
+ if ( 33 <= (*p) && (*p) <= 126 )
+ goto tr25;
+ goto st0;
tr25:
#line 44 "ext/puma_http11/http11_parser.rl"
{ MARK(mark, p); }
@@ -440,10 +443,14 @@ st19:
if ( ++p == pe )
goto _test_eof19;
case 19:
-#line 442 "ext/puma_http11/http11_parser.c"
- if ( (*p) == 13 )
- goto tr29;
- goto st19;
+#line 447 "ext/puma_http11/http11_parser.c"
+ switch( (*p) ) {
+ case 9: goto st19;
+ case 13: goto tr29;
+ }
+ if ( 32 <= (*p) && (*p) <= 126 )
+ goto st19;
+ goto st0;
tr9:
#line 51 "ext/puma_http11/http11_parser.rl"
{
diff --git a/ext/puma_http11/http11_parser_common.rl b/ext/puma_http11/http11_parser_common.rl
index a4cf89d..567a786 100644
--- a/ext/puma_http11/http11_parser_common.rl
+++ b/ext/puma_http11/http11_parser_common.rl
@@ -43,7 +43,7 @@
field_name = ( token -- ":" )+ >start_field $snake_upcase_field %write_field;
- field_value = any* >start_value %write_value;
+ field_value = ( print | "\t" )* >start_value %write_value;
message_header = field_name ":" " "* field_value :> CRLF;
diff --git a/ext/puma_http11/org/jruby/puma/Http11Parser.java b/ext/puma_http11/org/jruby/puma/Http11Parser.java
index 626ee81..92dd4ed 100644
--- a/ext/puma_http11/org/jruby/puma/Http11Parser.java
+++ b/ext/puma_http11/org/jruby/puma/Http11Parser.java
@@ -32,9 +32,9 @@ private static short[] init__puma_parser_key_offsets_0()
{
return new short [] {
0, 0, 8, 17, 27, 29, 30, 31, 32, 33, 34, 36,
- 39, 41, 44, 45, 61, 62, 78, 80, 81, 89, 97, 107,
- 115, 125, 134, 142, 150, 159, 168, 177, 186, 195, 204, 213,
- 222, 231, 240, 249, 258, 267, 276, 285, 294, 303, 312, 313
+ 39, 41, 44, 45, 61, 62, 78, 83, 87, 95, 103, 113,
+ 121, 130, 138, 146, 155, 164, 173, 182, 191, 200, 209, 218,
+ 227, 236, 245, 254, 263, 272, 281, 290, 299, 308, 309
};
}
@@ -50,27 +50,26 @@ private static char[] init__puma_parser_trans_keys_0()
46, 48, 57, 48, 57, 13, 48, 57, 10, 13, 33, 124,
126, 35, 39, 42, 43, 45, 46, 48, 57, 65, 90, 94,
122, 10, 33, 58, 124, 126, 35, 39, 42, 43, 45, 46,
- 48, 57, 65, 90, 94, 122, 13, 32, 13, 32, 60, 62,
- 127, 0, 31, 34, 35, 32, 60, 62, 127, 0, 31, 34,
- 35, 43, 58, 45, 46, 48, 57, 65, 90, 97, 122, 32,
- 34, 35, 60, 62, 127, 0, 31, 32, 34, 35, 59, 60,
- 62, 63, 127, 0, 31, 32, 34, 35, 60, 62, 63, 127,
- 0, 31, 32, 34, 35, 60, 62, 127, 0, 31, 32, 34,
- 35, 60, 62, 127, 0, 31, 32, 36, 95, 45, 46, 48,
- 57, 65, 90, 32, 36, 95, 45, 46, 48, 57, 65, 90,
- 32, 36, 95, 45, 46, 48, 57, 65, 90, 32, 36, 95,
- 45, 46, 48, 57, 65, 90, 32, 36, 95, 45, 46, 48,
- 57, 65, 90, 32, 36, 95, 45, 46, 48, 57, 65, 90,
- 32, 36, 95, 45, 46, 48, 57, 65, 90, 32, 36, 95,
- 45, 46, 48, 57, 65, 90, 32, 36, 95, 45, 46, 48,
- 57, 65, 90, 32, 36, 95, 45, 46, 48, 57, 65, 90,
- 32, 36, 95, 45, 46, 48, 57, 65, 90, 32, 36, 95,
- 45, 46, 48, 57, 65, 90, 32, 36, 95, 45, 46, 48,
- 57, 65, 90, 32, 36, 95, 45, 46, 48, 57, 65, 90,
- 32, 36, 95, 45, 46, 48, 57, 65, 90, 32, 36, 95,
- 45, 46, 48, 57, 65, 90, 32, 36, 95, 45, 46, 48,
- 57, 65, 90, 32, 36, 95, 45, 46, 48, 57, 65, 90,
- 32, 0
+ 48, 57, 65, 90, 94, 122, 9, 13, 32, 33, 126, 9,
+ 13, 32, 126, 32, 60, 62, 127, 0, 31, 34, 35, 32,
+ 60, 62, 127, 0, 31, 34, 35, 43, 58, 45, 46, 48,
+ 57, 65, 90, 97, 122, 32, 34, 35, 60, 62, 127, 0,
+ 31, 32, 34, 35, 60, 62, 63, 127, 0, 31, 32, 34,
+ 35, 60, 62, 127, 0, 31, 32, 34, 35, 60, 62, 127,
+ 0, 31, 32, 36, 95, 45, 46, 48, 57, 65, 90, 32,
+ 36, 95, 45, 46, 48, 57, 65, 90, 32, 36, 95, 45,
+ 46, 48, 57, 65, 90, 32, 36, 95, 45, 46, 48, 57,
+ 65, 90, 32, 36, 95, 45, 46, 48, 57, 65, 90, 32,
+ 36, 95, 45, 46, 48, 57, 65, 90, 32, 36, 95, 45,
+ 46, 48, 57, 65, 90, 32, 36, 95, 45, 46, 48, 57,
+ 65, 90, 32, 36, 95, 45, 46, 48, 57, 65, 90, 32,
+ 36, 95, 45, 46, 48, 57, 65, 90, 32, 36, 95, 45,
+ 46, 48, 57, 65, 90, 32, 36, 95, 45, 46, 48, 57,
+ 65, 90, 32, 36, 95, 45, 46, 48, 57, 65, 90, 32,
+ 36, 95, 45, 46, 48, 57, 65, 90, 32, 36, 95, 45,
+ 46, 48, 57, 65, 90, 32, 36, 95, 45, 46, 48, 57,
+ 65, 90, 32, 36, 95, 45, 46, 48, 57, 65, 90, 32,
+ 36, 95, 45, 46, 48, 57, 65, 90, 32, 0
};
}
@@ -81,7 +80,7 @@ private static byte[] init__puma_parser_single_lengths_0()
{
return new byte [] {
0, 2, 3, 4, 2, 1, 1, 1, 1, 1, 0, 1,
- 0, 1, 1, 4, 1, 4, 2, 1, 4, 4, 2, 6,
+ 0, 1, 1, 4, 1, 4, 3, 2, 4, 4, 2, 6,
8, 7, 6, 6, 3, 3, 3, 3, 3, 3, 3, 3,
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 1, 0
};
@@ -94,7 +93,7 @@ private static byte[] init__puma_parser_range_lengths_0()
{
return new byte [] {
0, 3, 3, 3, 0, 0, 0, 0, 0, 0, 1, 1,
- 1, 1, 0, 6, 0, 6, 0, 0, 2, 2, 4, 1,
+ 1, 1, 0, 6, 0, 6, 1, 1, 2, 2, 4, 1,
1, 1, 1, 1, 3, 3, 3, 3, 3, 3, 3, 3,
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 0
};
@@ -107,9 +106,9 @@ private static short[] init__puma_parser_index_offsets_0()
{
return new short [] {
0, 0, 6, 13, 21, 24, 26, 28, 30, 32, 34, 36,
- 39, 41, 44, 46, 57, 59, 70, 73, 75, 82, 89, 96,
- 104, 114, 123, 131, 139, 146, 153, 160, 167, 174, 181, 188,
- 195, 202, 209, 216, 223, 230, 237, 244, 251, 258, 265, 267
+ 39, 41, 44, 46, 57, 59, 70, 75, 79, 86, 93, 100,
+ 108, 117, 125, 133, 140, 147, 154, 161, 168, 175, 182, 189,
+ 196, 203, 210, 217, 224, 231, 238, 245, 252, 259, 261
};
}
@@ -124,24 +123,23 @@ private static byte[] init__puma_parser_indicies_0()
10, 1, 11, 1, 12, 1, 13, 1, 14, 1, 15, 1,
16, 15, 1, 17, 1, 18, 17, 1, 19, 1, 20, 21,
21, 21, 21, 21, 21, 21, 21, 21, 1, 22, 1, 23,
- 24, 23, 23, 23, 23, 23, 23, 23, 23, 1, 26, 27,
- 25, 29, 28, 30, 1, 1, 1, 1, 1, 31, 32, 1,
- 1, 1, 1, 1, 33, 34, 35, 34, 34, 34, 34, 1,
- 8, 1, 9, 1, 1, 1, 1, 35, 36, 1, 38, 39,
- 1, 1, 40, 1, 1, 37, 8, 1, 9, 1, 1, 42,
- 1, 1, 41, 43, 1, 45, 1, 1, 1, 1, 44, 46,
- 1, 48, 1, 1, 1, 1, 47, 2, 49, 49, 49, 49,
- 49, 1, 2, 50, 50, 50, 50, 50, 1, 2, 51, 51,
- 51, 51, 51, 1, 2, 52, 52, 52, 52, 52, 1, 2,
- 53, 53, 53, 53, 53, 1, 2, 54, 54, 54, 54, 54,
- 1, 2, 55, 55, 55, 55, 55, 1, 2, 56, 56, 56,
- 56, 56, 1, 2, 57, 57, 57, 57, 57, 1, 2, 58,
- 58, 58, 58, 58, 1, 2, 59, 59, 59, 59, 59, 1,
- 2, 60, 60, 60, 60, 60, 1, 2, 61, 61, 61, 61,
- 61, 1, 2, 62, 62, 62, 62, 62, 1, 2, 63, 63,
- 63, 63, 63, 1, 2, 64, 64, 64, 64, 64, 1, 2,
- 65, 65, 65, 65, 65, 1, 2, 66, 66, 66, 66, 66,
- 1, 2, 1, 1, 0
+ 24, 23, 23, 23, 23, 23, 23, 23, 23, 1, 25, 26,
+ 27, 25, 1, 28, 29, 28, 1, 30, 1, 1, 1, 1,
+ 1, 31, 32, 1, 1, 1, 1, 1, 33, 34, 35, 34,
+ 34, 34, 34, 1, 8, 1, 9, 1, 1, 1, 1, 35,
+ 36, 1, 38, 1, 1, 39, 1, 1, 37, 40, 1, 42,
+ 1, 1, 1, 1, 41, 43, 1, 45, 1, 1, 1, 1,
+ 44, 2, 46, 46, 46, 46, 46, 1, 2, 47, 47, 47,
+ 47, 47, 1, 2, 48, 48, 48, 48, 48, 1, 2, 49,
+ 49, 49, 49, 49, 1, 2, 50, 50, 50, 50, 50, 1,
+ 2, 51, 51, 51, 51, 51, 1, 2, 52, 52, 52, 52,
+ 52, 1, 2, 53, 53, 53, 53, 53, 1, 2, 54, 54,
+ 54, 54, 54, 1, 2, 55, 55, 55, 55, 55, 1, 2,
+ 56, 56, 56, 56, 56, 1, 2, 57, 57, 57, 57, 57,
+ 1, 2, 58, 58, 58, 58, 58, 1, 2, 59, 59, 59,
+ 59, 59, 1, 2, 60, 60, 60, 60, 60, 1, 2, 61,
+ 61, 61, 61, 61, 1, 2, 62, 62, 62, 62, 62, 1,
+ 2, 63, 63, 63, 63, 63, 1, 2, 1, 1, 0
};
}
diff --git a/test/test_http11.rb b/test/test_http11.rb
index 2a30047..79a8b75 100644
--- a/test/test_http11.rb
+++ b/test/test_http11.rb
@@ -183,4 +183,34 @@ class Http11ParserTest < Minitest::Test
end
end
+
+ def test_newline_smuggler
+ parser = Puma::HttpParser.new
+ req = {}
+ http = "GET / HTTP/1.1\r\nHost: localhost:8080\r\nDummy: x\nDummy2: y\r\n\r\n"
+
+ parser.execute(req, http, 0) rescue nil # We test the raise elsewhere.
+
+ assert parser.error?, "Parser SHOULD have error"
+ end
+
+ def test_newline_smuggler_two
+ parser = Puma::HttpParser.new
+ req = {}
+ http = "GET / HTTP/1.1\r\nHost: localhost:8080\r\nDummy: x\r\nDummy: y\nDummy2: z\r\n\r\n"
+
+ parser.execute(req, http, 0) rescue nil
+
+ assert parser.error?, "Parser SHOULD have error"
+ end
+
+ def test_htab_in_header_val
+ parser = Puma::HttpParser.new
+ req = {}
+ http = "GET / HTTP/1.1\r\nHost: localhost:8080\r\nDummy: Valid\tValue\r\n\r\n"
+
+ parser.execute(req, http, 0)
+
+ assert_equal "Valid\tValue", req['HTTP_DUMMY']
+ end
end
--
2.30.0