如果你使用 剥离字符 清理用户输入,你并不孤单。许多开发人员都依赖这种 输入净化 阻止注入尝试。乍一看,删除危险字符似乎合乎逻辑,有效载荷就会消失。然而,这种方法给人一种虚假的安全感。事实上,攻击者可以绕过简单的过滤器,例如 剥离字符 使用 混淆的有效载荷、编码或巧妙的上下文切换。这就是为什么聪明的开发人员不会止步于此。相反,他们会使用 参数化查询,从根源上阻止注入攻击。
在这篇文章中,您将了解原因 剥离字符 在实际场景中会如何失效,攻击者如何滥用这些过滤器,以及哪些安全替代方案实际上有效。我们将通过代码示例,展示常见的绕过技术,并解释如何 输入净化 必须始终与结构保护措施配合使用,例如 参数化查询,否则你就会一直处于脆弱状态。
什么是 剥离字符 确实如此(并且不如此)
许多开发人员使用 stripchar 或类似的函数,用于从用户输入中删除不安全的字符。通常,它会删除标点符号、特殊符号或任何非字母数字字符。乍一看,这听起来像是 输入净化,但这并不是真正的保护。
让我们分解一下。像这样的函数:
function stripchar(input) {
return input.replace(/[^\w\s]/gi, '');
}
删除如下字符 ', " 或 ;。因此,如果您输入:
'; DROP TABLE users; --
它变成:
DROP TABLE users
即使用户输入看起来很干净,攻击者仍然可以仅使用逻辑注入 SQL 有效负载,尤其是当应用程序通过字符串连接构建查询时。 真正防止SQL注入,则必须使用参数化查询和上下文感知输入处理。字符过滤器,例如 stripchar() 根本不够。
当然,精简的输入乍一看可能更安全。然而,这种方法并不能消除恶意逻辑,它只是改变了其编写方式。事实上,攻击者经常利用这一点,通过编码有效载荷、插入空格或策略性地使用已删除的字符来完全绕过你的过滤器。
除了, 剥离字符 缺乏关键上下文。它不知道输入是发往数据库、shell 还是浏览器。这意味着它无法应用正确的转义或编码。在不知道目标的情况下过滤输入就像在真正的威胁正在发生时转义 HTML 一样。 SQLi.
在最后, 剥离字符 它不会解释或保护任何内容,只会编辑字符串。而编辑本身并不安全。如果您想要真正的保护,请使用结构化、经过验证和参数化的查询。就这样。
为了使差异更明显,下面是 stripchar 与参数化查询的并排比较:
Stripchar 与参数化查询:哪一个实际上保护了您的代码?
| 特性 | stripchar() |
参数化查询 |
|---|---|---|
| 防护等级 | 基本字符串清理。可通过编码或逻辑技巧轻松绕过。 | 强力防御所有形式的 SQL 注入。 |
| 上下文意识 | 忽略上下文(SQL、HTML、shell 等)。同一条规则适用于所有情况。 | 完全上下文感知。针对每种环境使用适当的转义。 |
| 开发者的努力 | 实施起来很快,但长期使用不可靠。 | 需要正确的集成,但要强大且面向未来。 |
| 旁路电阻 | 低——攻击者可以轻松利用空格、编码或逻辑进行攻击。 | 高——将代码与数据分离并可靠地阻止注入。 |
| 安全信心 | 虚假的安全感——可能会隐藏问题而无法解决它。 | 值得信赖的行业 standard 用于安全查询执行。 |
攻击者如何绕过输入清理
当开发人员依赖 剥离字符 用于输入清理:
攻击者不需要破坏你的过滤器,他们只需要 绕过他们. 当开发人员依赖 剥离字符 对于输入过滤,他们通常认为删除引号或分号之类的字符就能阻止注入尝试。然而,攻击者很快就适应了。他们精心设计 混淆的有效载荷 这些错误会通过基于正则表达式的过滤器,特别是当这些过滤器缺乏上下文时。
例如,假设您尝试像这样清理输入:
const input = stripchar(userInput);
// safe to use? maybe not.
db.query("SELECT * FROM users WHERE name = '" + input + "'");
即使用户无法提交经典 ' OR 1=1 --他们可以使用Unicode技巧、字符串连接或仍然有效的语法。像这样的有效载荷通常有效:
0x27206F7220313D31--
要么:
'+UNION+SELECT+null,null,null--
如果你的函数删除了非单词字符,你可以 意外地重建了有效的 SQL 命令更糟糕的是,攻击者可以以通过过滤器但被目标系统解码的方式对值进行编码。
除了 SQL 注入之外, 剥离字符 在其他情况下也会失败,例如 Shell 命令、文件路径,甚至 JavaScript 执行。由于它无法感知输入将在何处使用,因此无法应用正确的转义或验证。
其结果是, 输入净化 - 剥离字符 很容易绕过。真正的安全来自于 上下文感知控制,特别是 参数化查询 完全防止逻辑注入。
为什么应该使用参数化查询
如果你想真正阻止注入攻击,你需要 停止使用字符串构建查询。 那是在哪里 参数化查询 进来。不像 剥离字符,他们不过滤,他们 将代码与数据分开 在引擎层面。
让我们重新审视一下这个有问题的查询:
const input = stripchar(userInput);
const query = "SELECT * FROM users WHERE name = '" + input + "'";
这很危险,因为输入会被直接注入到 SQL 中。即使进行了字符剥离,你仍然会构建一个可能被滥用的字符串。相反,请使用如下参数化查询:
const query = "SELECT * FROM users WHERE name = ?";
db.execute(query, [userInput]);
这里,数据库驱动程序知道 userInput 是数据, 不可执行代码。它会自动转义并阻止注入,即使输入包含引号、分号或十六进制编码的有效负载。
在 Python 中:
cursor.execute("SELECT * FROM users WHERE name = %s", (user_input,))
在带有 PDO 的 PHP 中:
$stmt = $pdo->prepare("SELECT * FROM users WHERE name = :name");
$stmt->execute(['name' => $input]);
在所有这些例子中, 参数化查询 防止注入,无需猜测哪些字符可能存在危险。你不需要 剥离炭, 您需要结构化的、上下文感知的查询构造。
此外,该技术还可以阻止混淆的有效载荷、Unicode 技巧和编码绕过,这些是 XSS 漏洞。Xygeni 等工具可及早发现这些威胁 SAST 分析.
简而言之,真正的防御不依赖于过滤器。它们依赖于协议、可信 API 和完整的上下文。如果您使用框架或动态服务注入,请注意输入如何在代码库中传播。 安全依赖注入 确保即使复杂的流程也不会出现新的攻击面。
不要依赖 剥离字符. 使用 Xygeni 来加强真正的防御
即使你使用 参数化查询,不能保证你的整个代码库都遵循相同的 standard遗留逻辑、第三方脚本或 PR 中被忽略的行仍然可能带来注入风险。而这正是 Xygeni 能够提供帮助的地方。
Xygeni 扫描您的源代码, pull requests和 CI pipeline要捕捉的:
- 通过连接构建 SQL 的查询字符串
- 弱的或自制的过滤器,例如 剥离字符
- 与已知混淆有效载荷相匹配的可疑逻辑
您无需仔细检查每一行。Xygeni 会及早标记不安全的模式,并应用 自动修复 在可能的情况下,可以通过可定制的 Guardrails.
总之, Xygeni 确保参数化查询不仅仅是一种最佳实践,而且可以大规模实施。 无需猜测,无需错过任何筛选条件,真正保护您的安全。
关键要点:需要记住什么 剥离字符 和注入风险
- 剥离字符 不是安全功能 — 它消除的是字符,而不是风险。
- 输入净化还不够 当您使用字符串连接构建查询时。
- 参数化查询是正确的防御方式,并且每种现代语言或框架都支持它们。
- 混淆的有效载荷可以绕过过滤器,特别是涉及编码技巧时。
- 静态分析(SAST)工具捕捉人类错过的东西,包括隐藏在遗留代码中的不安全模式。
- Xygeni 实现自动检测、优先级排序甚至修复 这样您的团队就可以专注于编写功能,而不是追逐漏洞。
结论:不要相信过滤器。安全源于设计。
依靠以下函数 剥离字符 看似快速修复,却会造成虚假的安全感。攻击者的进化速度比字符串过滤器更快。阻止注入攻击的唯一可靠方法是精心设计编写安全代码,并在所有地方强制执行该设计。
像 Xygeni 这样的工具可以帮助你自动完成这项工作。 pull request 至 pipeline,它们会捕获您的过滤器无法捕获的问题,并在产品投入生产之前进行修复。





