CodeQL 文档

字符串转义或编码不完整

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

点击查看 CodeQL 代码库中的查询

清理不受信任的输入是防止注入攻击(如 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

参考资料

  • ©GitHub, Inc.
  • 条款
  • 隐私