Merge pull request from GHSA-84j7-475p-hp8v

header value could inject a CR or LF and inject their own HTTP response.
This commit is contained in:
Nate Berkopec 2020-02-27 11:52:27 -06:00
parent bb29fc7fe8
commit 1b17e85a06
No known key found for this signature in database
GPG Key ID: BDD7A4B8E43906A6
8 changed files with 62 additions and 0 deletions

8
benchmarks/wrk/hello.sh Executable file
View File

@ -0,0 +1,8 @@
# You are encouraged to use @ioquatix's wrk fork, located here: https://github.com/ioquatix/wrk
bundle exec bin/puma -t 4 test/rackup/hello.ru &
PID1=$!
sleep 5
wrk -c 4 -d 30 --latency http://localhost:9292
kill $PID1

View File

@ -0,0 +1,6 @@
bundle exec bin/puma -t 4 test/rackup/many_long_headers.ru &
PID1=$!
sleep 5
wrk -c 4 -d 30 --latency http://localhost:9292
kill $PID1

View File

@ -0,0 +1,6 @@
bundle exec bin/puma -t 4 test/rackup/realistic_response.ru &
PID1=$!
sleep 5
wrk -c 4 -d 30 --latency http://localhost:9292
kill $PID1

View File

@ -228,6 +228,7 @@ module Puma
COLON = ": ".freeze
NEWLINE = "\n".freeze
CRLF_REGEX = /[\r\n]/.freeze
HIJACK_P = "rack.hijack?".freeze
HIJACK = "rack.hijack".freeze

View File

@ -674,6 +674,8 @@ module Puma
status, headers, res_body = @app.call(env)
return :async if req.hijacked
# Checking to see if an attacker is trying to inject headers into the response
headers.reject! { |_k, v| CRLF_REGEX =~ v.to_s }
status = status.to_i

View File

@ -0,0 +1,9 @@
require 'securerandom'
long_header_hash = {}
30.times do |i|
long_header_hash["X-My-Header-#{i}"] = SecureRandom.hex(1000)
end
run lambda { |env| [200, long_header_hash, ["Hello World"]] }

View File

@ -0,0 +1,11 @@
require 'securerandom'
long_header_hash = {}
25.times do |i|
long_header_hash["X-My-Header-#{i}"] = SecureRandom.hex(25)
end
response = SecureRandom.hex(100_000) # A 100kb document
run lambda { |env| [200, long_header_hash.dup, [response.dup]] }

View File

@ -740,4 +740,23 @@ EOF
assert_equal "HTTP/1.0 200 OK\r\nX-Empty-Header: \r\n\r\n", data
end
# https://github.com/ruby/ruby/commit/d9d4a28f1cdd05a0e8dabb36d747d40bbcc30f16
def test_prevent_response_splitting_headers
server_run app: ->(_) { [200, {'X-header' => "malicious\r\nCookie: hack"}, ["Hello"]] }
data = send_http_and_read "HEAD / HTTP/1.0\r\n\r\n"
refute_match 'hack', data
end
def test_prevent_response_splitting_headers_cr
server_run app: ->(_) { [200, {'X-header' => "malicious\rCookie: hack"}, ["Hello"]] }
data = send_http_and_read "HEAD / HTTP/1.0\r\n\r\n"
refute_match 'hack', data
end
def test_prevent_response_splitting_headers_lf
server_run app: ->(_) { [200, {'X-header' => "malicious\nCookie: hack"}, ["Hello"]] }
data = send_http_and_read "HEAD / HTTP/1.0\r\n\r\n"
refute_match 'hack', data
end
end