字符串转义或编码不完整¶
ID: rb/incomplete-sanitization
Kind: problem
Security severity: 7.8
Severity: warning
Precision: high
Tags:
- correctness
- security
- external/cwe/cwe-020
- external/cwe/cwe-080
- external/cwe/cwe-116
Query suites:
- ruby-code-scanning.qls
- ruby-security-extended.qls
- ruby-security-and-quality.qls
清理不受信任的输入是防止注入攻击(如 SQL 注入或跨站脚本攻击)的常用技术。通常,这是通过以特定于域的方式转义元字符(如引号)来实现的,以便它们被视为普通字符。
但是,直接使用 String#sub
方法执行转义非常容易出错。常见的错误包括只替换元字符的第一个出现,或者对各种元字符进行反斜杠转义,但不对反斜杠本身进行转义。
在前一种情况下,后面的元字符保持不变,并可用于破坏清理。在后一种情况下,在元字符之前加上反斜杠会导致反斜杠被转义,但元字符显示为未转义,这再次使清理无效。
即使转义后的字符串未用于安全关键的上下文中,不完整的转义仍然可能产生不希望的结果,例如渲染错误或输出混乱。
建议¶
如果可能,请使用(经过充分测试的)清理库。这些库比自定义实现更可能正确处理极端情况。
更安全的替代方法是设计应用程序,使其不需要清理。否则,请确保使用 String#gsub
而不是 String#sub
,以确保替换所有出现的情况,并记住在适用时转义反斜杠。
示例¶
例如,假设我们希望将用户控制的字符串 account_number
嵌入到 SQL 查询中作为字符串文字的一部分。为了避免 SQL 注入,我们需要确保字符串不包含未转义的单引号字符。以下方法尝试通过将单引号加倍来确保这一点,从而对它们进行转义
def escape_quotes(s)
s.sub "'", "''"
end
按此编写,此清理器无效:String#sub
只会替换该字符串的第一个出现。
如上所述,escape_quotes
方法应替换为专门的清理器,例如 Rails 中的 ActiveRecord::Base::sanitize_sql
,或使用自动清理参数的 ORM 方法。
如果这不是一种选择,则应将 escape_quotes
重写为使用 String#gsub
方法
def escape_quotes(s)
s.gsub "'", "''"
end