From 313dd6a05a5924ed6c82072299c53fed09e39ae7 Mon Sep 17 00:00:00 2001 From: Patrick Tulskie Date: Wed, 22 Aug 2018 12:56:43 -0400 Subject: [PATCH] Whitelist http/https schemes [CVE-2018-16471] --- lib/rack/request.rb | 21 +++++++++++++++++---- test/spec_request.rb | 5 +++++ 2 files changed, 22 insertions(+), 4 deletions(-) diff --git a/lib/rack/request.rb b/lib/rack/request.rb index 2a00de7..6307b61 100644 --- a/lib/rack/request.rb +++ b/lib/rack/request.rb @@ -11,6 +11,8 @@ module Rack # req.params["data"] class Request + SCHEME_WHITELIST = %w(https http).freeze + def initialize(env) @params = nil super(env) @@ -188,10 +190,8 @@ module Rack 'https' elsif get_header(HTTP_X_FORWARDED_SSL) == 'on' 'https' - elsif get_header(HTTP_X_FORWARDED_SCHEME) - get_header(HTTP_X_FORWARDED_SCHEME) - elsif get_header(HTTP_X_FORWARDED_PROTO) - get_header(HTTP_X_FORWARDED_PROTO).split(',')[0] + elsif forwarded_scheme + forwarded_scheme else get_header(RACK_URL_SCHEME) end @@ -479,6 +479,19 @@ module Rack def reject_trusted_ip_addresses(ip_addresses) ip_addresses.reject { |ip| trusted_proxy?(ip) } end + + def forwarded_scheme + scheme_headers = [ + get_header(HTTP_X_FORWARDED_SCHEME), + get_header(HTTP_X_FORWARDED_PROTO).to_s.split(',')[0] + ] + + scheme_headers.each do |header| + return header if SCHEME_WHITELIST.include?(header) + end + + nil + end end include Env diff --git a/test/spec_request.rb b/test/spec_request.rb index bdad68f..cfaedbc 100644 --- a/test/spec_request.rb +++ b/test/spec_request.rb @@ -572,6 +572,11 @@ class RackRequestTest < Minitest::Spec request.must_be :ssl? end + it "prevents scheme abuse" do + request = make_request(Rack::MockRequest.env_for("/", 'HTTP_X_FORWARDED_SCHEME' => 'a.">')) + request.scheme.must_equal 'http' + end + it "parse cookies" do req = make_request \ Rack::MockRequest.env_for("", "HTTP_COOKIE" => "foo=bar;quux=h&m") -- 2.17.0