不完整的多字符清理¶
ID: js/incomplete-multi-character-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:
- javascript-code-scanning.qls
- javascript-security-extended.qls
- javascript-security-and-quality.qls
清理不受信任的输入是防止注入攻击和其他安全漏洞的常见技术。正则表达式经常被用于执行此清理。但是,当正则表达式匹配多个连续字符时,仅替换一次会导致不安全文本在清理后的输入中重新出现。
攻击者可以利用此问题来构造输入,这些输入在使用无效的正则表达式清理后仍然包含恶意代码或内容。这会导致代码执行、数据泄露或其他漏洞。
建议¶
为了防止此问题,强烈建议尽可能使用经过良好测试的清理库。这些库更有可能处理边缘情况并确保有效清理。
如果库不可用,您可以考虑其他策略来解决此问题。例如,反复应用正则表达式替换,直到不再进行任何替换,或者重写正则表达式以匹配单个字符而不是整个不安全文本。
示例¶
考虑以下旨在删除所有 HTML 注释开始和结束标签的 JavaScript 代码
str.replace(/<!--|--!?>/g, "");
给定输入字符串“<!<!— comment —>>”,输出将为“<!– comment –>”,其中仍然包含 HTML 注释。
解决此问题的一种可能方法是反复应用正则表达式替换,直到不再进行任何替换。这可以确保不安全文本不会在清理后的输入中重新出现,从而有效地删除目标模式的所有实例
function removeHtmlComments(input) {
let previous;
do {
previous = input;
input = input.replace(/<!--|--!?>/g, "");
} while (input !== previous);
return input;
}
示例¶
另一个示例是以下旨在删除脚本标签的正则表达式
str.replace(/<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/g, "");
如果输入字符串为“<scrip<script>is removed</script>t>alert(123)</script>”,输出将为“<script>alert(123)</script>”,其中仍然包含脚本标签。
解决此问题的一种方法是重写正则表达式以匹配单个字符(“<”和“>”),而不是整个不安全文本。这简化了清理过程,并确保所有潜在的不安全字符都被删除
function removeAllHtmlTags(input) {
return input.replace(/<|>/g, "");
}
另一种可能的解决方案是使用流行的 sanitize-html
npm 库。它保留了大多数安全的 HTML 标签,同时删除所有不安全的标签和属性。
const sanitizeHtml = require("sanitize-html");
function removeAllHtmlTags(input) {
return sanitizeHtml(input);
}
示例¶
最后,考虑使用正则表达式 /\.\.\//
的路径清理器
str.replace(/\.\.\//g, "");
正则表达式试图从 str
中删除所有 /../
的出现。这不会按预期工作:例如,对于字符串 /./.././
,它将删除中间的 /../
的单个出现,但字符串的其余部分将变为 /../
,这是我们试图删除的子字符串的另一个实例。
解决此问题的一种可能方法是使用“sanitize-filename” npm 库进行路径清理。此库专门设计用于处理路径清理,并且应该处理所有边缘情况并确保有效清理
const sanitize = require("sanitize-filename");
function sanitizePath(input) {
return sanitize(input);
}
参考¶
OWASP Top 10: A1 注入.
Stack Overflow: 使用 JS 正则表达式从 HTML 中删除所有脚本标签.
常见弱点枚举:CWE-20。
常见弱点枚举:CWE-80。
常见弱点枚举:CWE-116。