不安全的 HTML 过滤正则表达式¶
ID: rb/bad-tag-filter
Kind: problem
Security severity: 7.8
Severity: warning
Precision: high
Tags:
- correctness
- security
- external/cwe/cwe-116
- external/cwe/cwe-020
- external/cwe/cwe-185
- external/cwe/cwe-186
Query suites:
- ruby-code-scanning.qls
- ruby-security-extended.qls
- ruby-security-and-quality.qls
可以使用正则表达式匹配一些单个 HTML 标签(使用正则表达式解析通用 HTML 是不可能的)。但是,如果正则表达式编写不当,则可能会绕过它,这会导致跨站脚本或其他安全问题。
一些错误是由浏览器具有非常宽松的 HTML 解析器引起的,并且通常会呈现包含语法错误的无效 HTML。尝试匹配 HTML 的正则表达式也应该识别包含此类语法错误的标签。
建议¶
如果可能,请使用经过充分测试的清理或解析库。这些库比自定义实现更有可能正确处理极端情况。
示例¶
以下示例尝试过滤掉所有 <script> 标签。
def filter_script_tags(html)
old_html = ""
while (html != old_html)
old_html = html
html = html.gsub(/<script[^>]*>.*<\/script>/m, "")
end
html
end
上面的清理程序不会过滤掉所有 <script> 标签。浏览器不仅会接受 </script> 作为脚本结束标签,还会接受 </script foo="bar"> 等标签,即使它是解析器错误。这意味着攻击字符串,例如 <script>alert(1)</script foo="bar">,不会被该函数过滤,如果该字符串被渲染为 HTML,浏览器将执行 alert(1)。
其他极端情况包括 HTML 注释可以以 --!> 结尾,以及 HTML 标签名称可以包含大写字母。
参考资料¶
Securitum:复制和粘贴的奇特案例.
stackoverflow.com:你不能用正则表达式解析 [X]HTML.
HTML 标准:注释结束感叹号状态.
stackoverflow.com:为什么浏览器对 HTML 不严格?.
常见弱点枚举:CWE-116.
常见弱点枚举:CWE-20.
常见弱点枚举:CWE-185.
常见弱点枚举:CWE-186.