Filter sensitive query string parameters in the log [#6244 state:committed]

This provides more safety to applications that put secret information in the query string, such as API keys or SSO tokens.

Signed-off-by: Xavier Noria <fxn@hashref.com>
This commit is contained in:
Prem Sichanugrist & Xavier Noria 2011-01-01 23:51:05 +07:00 committed by Xavier Noria
parent 51a269b228
commit 68802d0fbe
4 changed files with 58 additions and 5 deletions

View File

@ -1,5 +1,7 @@
*Rails 3.1.0 (unreleased)*
* Sensitive query string parameters (specified in config.filter_parameters) will now be filtered out from the request paths in the log file. [Prem Sichanugrist, fxn]
* URL parameters which return false for to_param now appear in the query string (previously they were removed) [Andrew White]
* URL parameters which return nil for to_param are now removed from the query string [Andrew White]

View File

@ -5,10 +5,10 @@ require 'active_support/core_ext/object/duplicable'
module ActionDispatch
module Http
# Allows you to specify sensitive parameters which will be replaced from
# the request log by looking in all subhashes of the param hash for keys
# to filter. If a block is given, each key and value of the parameter
# hash and all subhashes is passed to it, the value or key can be replaced
# using String#replace or similar method.
# the request log by looking in the query string of the request and all
# subhashes of the params hash to filter. If a block is given, each key and
# value of the params hash and all subhashes is passed to it, the value
# or key can be replaced using String#replace or similar method.
#
# Examples:
#
@ -38,6 +38,11 @@ module ActionDispatch
@filtered_env ||= env_filter.filter(@env)
end
# Reconstructed a path with all sensitive GET parameters replaced.
def filtered_path
@filtered_path ||= query_string.empty? ? path : "#{path}?#{filtered_query_string}"
end
protected
def parameter_filter
@ -52,6 +57,14 @@ module ActionDispatch
@@parameter_filter_for[filters] ||= ParameterFilter.new(filters)
end
KV_RE = '[^&;=]+'
PAIR_RE = %r{(#{KV_RE})=(#{KV_RE})}
def filtered_query_string
query_string.gsub(PAIR_RE) do |_|
parameter_filter.filter([[$1, $2]]).first.join("=")
end
end
end
end
end

View File

@ -518,6 +518,44 @@ class RequestTest < ActiveSupport::TestCase
assert_equal "1", request.params["step"]
end
test "filtered_path returns path with filtered query string" do
%w(; &).each do |sep|
request = stub_request('QUERY_STRING' => %w(username=sikachu secret=bd4f21f api_key=b1bc3b3cd352f68d79d7).join(sep),
'PATH_INFO' => '/authenticate',
'action_dispatch.parameter_filter' => [:secret, :api_key])
path = request.filtered_path
assert_equal %w(/authenticate?username=sikachu secret=[FILTERED] api_key=[FILTERED]).join(sep), path
end
end
test "filtered_path should not unescape a genuine '[FILTERED]' value" do
request = stub_request('QUERY_STRING' => "secret=bd4f21f&genuine=%5BFILTERED%5D",
'PATH_INFO' => '/authenticate',
'action_dispatch.parameter_filter' => [:secret])
path = request.filtered_path
assert_equal "/authenticate?secret=[FILTERED]&genuine=%5BFILTERED%5D", path
end
test "filtered_path should preserve duplication of keys in query string" do
request = stub_request('QUERY_STRING' => "username=sikachu&secret=bd4f21f&username=fxn",
'PATH_INFO' => '/authenticate',
'action_dispatch.parameter_filter' => [:secret])
path = request.filtered_path
assert_equal "/authenticate?username=sikachu&secret=[FILTERED]&username=fxn", path
end
test "filtered_path should ignore searchparts" do
request = stub_request('QUERY_STRING' => "secret",
'PATH_INFO' => '/authenticate',
'action_dispatch.parameter_filter' => [:secret])
path = request.filtered_path
assert_equal "/authenticate?secret", path
end
protected
def stub_request(env = {})

View File

@ -19,7 +19,7 @@ module Rails
def before_dispatch(env)
request = ActionDispatch::Request.new(env)
path = request.fullpath
path = request.filtered_path
info "\n\nStarted #{request.request_method} \"#{path}\" " \
"for #{request.ip} at #{Time.now.to_default_s}"