我不是保安。我是一名必须维护安全代码的程序员。这就是我所说的“脆弱”实践。入口点分散在一个典型的项目中。找到并清理所有这些需要大量的工作来解决一个问题,需要大量的仔细维护和麻烦,以确保它在代码更改时仍然有效,并且充满了使其无效的假设。
取而代之的是使用更易于维护、分层、上下文相关并解决广泛问题的实践。那么你就不需要昂贵的、过于宽泛的过滤了。
如果您不知道如何使用它们,则无法保护输入。
假设您通过从所有输入中删除所有单引号来“保护”您的系统。太好了,您可以安全地抵御一种SQL 注入攻击。如果该输入用于...
- 允许双引号的 MySQL 查询
- 文件系统操作
- 外壳命令
- 网络查询
- 方法名称
- 班级名称
eval
其中每一个都有不同的特殊字符、转义序列、引用规则和安全实践。您无法预测输入时将如何使用它。试图去除所有特殊字符是疯狂的,并且只能“解决”一类攻击。
或者如果允许用户输入页面限制怎么办。在参数化查询中尽职尽责地使用了该限制;没有 SQL 注入,耶!用户进入9999999999
,现在您对 DOS 攻击持开放态度。
您必须在执行可能不安全的操作时应用适当的安全措施。这考虑了许多独特的操作因素;清理输入字符只是其中之一。
只要你这样做,你也可以参数化你的查询。然后不再需要做所有的工作和毯子剥离报价的损坏。
过滤所有输入很困难。
在给定的项目中,有很多很多很多方法可以获取和传递输入:
- 表单输入
- 网址
- 文件名
- 文件内容
- 数据库查询
- 网络读取
- 环境变量
这些通常是非常自由的形式,可以使用许多不同的库。我不知道有任何静态分析工具可以验证所有潜在易受攻击的输入都经过过滤。有些语言有taint
系统,但很难有效使用。即使您过滤所有输入,如果没有静态分析工具,未过滤的输入也会随着开发的进行而泄漏回来。维护一个妨碍功能的不完整、昂贵的结果需要付出很多努力。
相反,通常只有一种方法可以在项目中执行 SQL。存在静态和运行时工具来自动检测潜在的 SQL 注入。您甚至可以完全禁止字符串,并要求所有查询都是 SQL 查询对象。这些良好实践易于维护,并且越来越多地融入工具和 SQL 库中。
“防火墙”导致安全性松懈。
类似于某些办公网络因为“我们有防火墙”而具有非常不安全的做法,团队也有可能因为“输入是安全的”而变得懒惰保护他们的代码。输入绝对不安全。
有些人可能会说“为什么不两者兼而有之?” 你只有这么多的时间来做一个项目。低效率、高维护的做法是浪费时间。实施和维护它将使您的有限时间远离更高效、更易于维护的做法。在最坏的情况下,您将花费大量时间与输入进行打地鼠游戏,以及由过于激进的过滤引起的后续问题,您将永远没有时间采取适当的安全措施。
简而言之,输入过滤是昂贵的、泄漏的、难以维护的,不能解决问题,并且可能会使情况变得更糟。