The built-in Rails logging system contains a significant amount of information about the running application - such as record of all requests, parameters sent, and queries performed. By default, the production log contains full requests and the value of every parameter, with no discretion.
An attacker who obtains the Rails production log could stumble upon an absolute gold mine of sensitive information. The log could contain passwords to thousands of accounts, credit cart numbers, and personally identifiable information such as social security numbers or contact information. What’s worse is that there is rarely adequate protection on log files, as they are frequently overlooked by administrators and developers. Besides the obvious security hazards of leaving this sensitive information lying around - it is also mandatory to protect it if you are required to comply with standards such as the PCI DSS.
Although the log files should be protected, it’s better to not log sensitive data at all, if it is not entirely necessary. Fortunately, Rails provides a simple one-liner to filter out sensitive parameters from the logs. Place the following line in your ApplicationController, listing each sensitive parameter.
filter_parameter_logging :password, :password_confirmation, :credit_card, :ssn
This will replace the values of the specified parameters with “[FILTERED]” before they are logged to the production log. However, it will not filter out sensitive parameters that have already been logged! If you have been running your app in production before applying this fix, you will need to take additional steps to filter out the existing logs.
Filtering existing log files
The method above will not filter existing log entries. If you already have sensitive data in your production log, you will need to filter it out. Below is a simple ruby script to filter your existing production log.
# List of parameters to filter out of the log file. Should include
# passwords and personal data such as social security #, credit cards,
# etc.
filter_words = %w{ password password_confirmation address_1 address_2 }
# Read old log file into an array
dirty = *open(”production.log”, “r”)
File.open(”clean.log”, “w”) do |clean|
dirty.each do |line|
# Filter out each parameter specified in filter_words[]
filter_words.each { |word| line.sub!(/\”#{word}\”=>\”.*?\”/, “\”#{word}\”=>\”[FILTERED]\”")) }
end
end
Posts