日志注入¶
ID: rb/log-injection
Kind: path-problem
Security severity: 7.8
Severity: error
Precision: medium
Tags:
- security
- external/cwe/cwe-117
Query suites:
- ruby-security-extended.qls
- ruby-security-and-quality.qls
如果将未经清理的用户输入写入日志条目,恶意用户可能能够伪造新的日志条目。
当日志输出显示时,如果用户提供了一些在解释时会被解释为字符的输入,则可能会发生伪造。如果日志以纯文本文件形式显示,则恶意用户可以使用换行符。如果日志以 HTML 形式显示,则可以包含任意 HTML 来伪造日志条目。
建议¶
用户输入应在记录之前进行适当的清理。清理方式取决于日志条目将如何显示或使用。
如果日志条目为纯文本,则应使用 String#gsub
或类似方法从用户输入中删除换行符。还应注意在日志条目中明确标记用户输入。
对于将在 HTML 中显示的日志条目,用户输入应在记录之前进行 HTML 编码,以防止伪造和其他形式的 HTML 注入。
示例¶
在示例中,使用 `Logger#info` 记录用户提供的用户名。
在第一个案例中,它是直接记录的,没有进行任何清理。如果恶意用户提供 `username=Guest%0a[INFO]+User:+Admin%0a` 作为用户名参数,则日志条目将被拆分为两行,其中第二行将是 `[INFO]+User:+Admin`。
require 'logger'
class UsersController < ApplicationController
def login
logger = Logger.new STDOUT
username = params[:username]
# BAD: log message constructed with unsanitized user input
logger.info "attempting to login user: " + username
# ... login logic ...
end
end
在第二个示例中,使用 String#gsub
确保用户输入中没有换行符。
require 'logger'
class UsersController < ApplicationController
def login
logger = Logger.new STDOUT
username = params[:username]
# GOOD: log message constructed with sanitized user input
logger.info "attempting to login user: " + sanitized_username.gsub("\n", "")
# ... login logic ...
end
end