|
| 1 | +From 96c29264519374ee41eaf27933d5049528264e98 Mon Sep 17 00:00:00 2001 |
| 2 | +From: Jeremy Evans < [email protected]> |
| 3 | +Date: Tue, 15 Aug 2023 14:37:59 -0700 |
| 4 | +Subject: [PATCH] Raise HTTPStatus::BadRequest for requests with |
| 5 | + invalid/duplicate content-length headers |
| 6 | + |
| 7 | +Addresses CVE-2023-40225. |
| 8 | + |
| 9 | +Fixes #119 |
| 10 | +--- |
| 11 | + lib/webrick/httprequest.rb | 8 ++++++++ |
| 12 | + test/webrick/test_httprequest.rb | 25 +++++++++++++++++++++++++ |
| 13 | + 2 files changed, 33 insertions(+) |
| 14 | + |
| 15 | +diff --git a/lib/webrick/httprequest.rb b/lib/webrick/httprequest.rb |
| 16 | +index 680ac65a..7a1686bc 100644 |
| 17 | +--- a/lib/webrick/httprequest.rb |
| 18 | ++++ b/lib/webrick/httprequest.rb |
| 19 | +@@ -479,6 +479,14 @@ def read_header(socket) |
| 20 | + end |
| 21 | + end |
| 22 | + @header = HTTPUtils::parse_header(@raw_header.join) |
| 23 | ++ |
| 24 | ++ if (content_length = @header['content-length']) && content_length.length != 0 |
| 25 | ++ if content_length.length > 1 |
| 26 | ++ raise HTTPStatus::BadRequest, "multiple content-length request headers" |
| 27 | ++ elsif !/\A\d+\z/.match?(content_length[0]) |
| 28 | ++ raise HTTPStatus::BadRequest, "invalid content-length request header" |
| 29 | ++ end |
| 30 | ++ end |
| 31 | + end |
| 32 | + |
| 33 | + def parse_uri(str, scheme="http") |
| 34 | +diff --git a/test/webrick/test_httprequest.rb b/test/webrick/test_httprequest.rb |
| 35 | +index 2ff08d63..90332171 100644 |
| 36 | +--- a/test/webrick/test_httprequest.rb |
| 37 | ++++ b/test/webrick/test_httprequest.rb |
| 38 | +@@ -81,6 +81,31 @@ def test_request_uri_too_large |
| 39 | + } |
| 40 | + end |
| 41 | + |
| 42 | ++ def test_invalid_content_length_header |
| 43 | ++ ['', ' ', ' +1', ' -1', ' a'].each do |cl| |
| 44 | ++ msg = <<-_end_of_message_ |
| 45 | ++ GET / HTTP/1.1 |
| 46 | ++ Content-Length:#{cl} |
| 47 | ++ _end_of_message_ |
| 48 | ++ req = WEBrick::HTTPRequest.new(WEBrick::Config::HTTP) |
| 49 | ++ assert_raise(WEBrick::HTTPStatus::BadRequest){ |
| 50 | ++ req.parse(StringIO.new(msg.gsub(/^ {8}/, ""))) |
| 51 | ++ } |
| 52 | ++ end |
| 53 | ++ end |
| 54 | ++ |
| 55 | ++ def test_duplicate_content_length_header |
| 56 | ++ msg = <<-_end_of_message_ |
| 57 | ++ GET / HTTP/1.1 |
| 58 | ++ Content-Length: 1 |
| 59 | ++ Content-Length: 2 |
| 60 | ++ _end_of_message_ |
| 61 | ++ req = WEBrick::HTTPRequest.new(WEBrick::Config::HTTP) |
| 62 | ++ assert_raise(WEBrick::HTTPStatus::BadRequest){ |
| 63 | ++ req.parse(StringIO.new(msg.gsub(/^ {6}/, ""))) |
| 64 | ++ } |
| 65 | ++ end |
| 66 | ++ |
| 67 | + def test_parse_headers |
| 68 | + msg = <<-_end_of_message_ |
| 69 | + GET /path HTTP/1.1 |
0 commit comments