我正在更新一些不能正确处理用户输入的遗留代码。该代码确实进行了最少量的清理,但并未涵盖所有已知威胁。
我们较新的代码使用参数化查询。据我了解,查询是预编译的,输入被简单地视为无法执行的数据。在这种情况下,不需要消毒。那正确吗?
换句话说,如果我在这个遗留代码中参数化查询,是否可以消除它当前所做的清理工作?还是我错过了参数化之上的一些额外的清理好处?
我正在更新一些不能正确处理用户输入的遗留代码。该代码确实进行了最少量的清理,但并未涵盖所有已知威胁。
我们较新的代码使用参数化查询。据我了解,查询是预编译的,输入被简单地视为无法执行的数据。在这种情况下,不需要消毒。那正确吗?
换句话说,如果我在这个遗留代码中参数化查询,是否可以消除它当前所做的清理工作?还是我错过了参数化之上的一些额外的清理好处?
SQL 查询参数确实可以很好地防御 SQL 注入。嵌入的引号或其他特殊字符不会造成恶作剧。
但是 SQL 查询的某些组件不能参数化。例如表名、列名、SQL 关键字。
$sql = "SELECT * FROM MyTable ORDER BY {$columnname} {$ASC_or_DESC}";
因此,在插入 SQL 查询之前,您可能需要验证一些动态内容示例。将值列入白名单也是一种很好的技术。
此外,您可能拥有列的数据类型允许但没有意义的值。对于这些情况,使用应用程序代码进行验证通常比尝试在 SQL 约束中进行验证更容易。
假设您存储了一个信用卡号。信用卡号有有效的模式,图书馆可以识别有效的和无效的。
或者当用户定义她的密码时怎么样?您可能希望确保足够的密码强度,或验证用户在两个密码输入字段中输入了相同的字符串。
或者,如果他们订购了一定数量的商品,您可能需要将数量存储为整数,但您需要确保它大于零,如果大于 1000,您可能需要与用户再次核对他们输入正确。
参数化查询将有助于防止 SQL 注入,但它们不会对跨站点脚本做任何事。您需要其他措施(例如 HTML 编码或 HTML 检测/验证)来防止这种情况发生。如果您只关心 SQL 注入,那么参数化查询可能就足够了。
清理和验证有许多不同的原因,包括防止跨站点脚本,以及只需要字段的正确内容(电话号码中没有姓名)。参数化查询消除了手动清理或逃避 SQL 注入的需要。
请参阅我以前的答案之一。
简而言之,没有。输入清理和参数化查询的使用不是相互排斥的,它们是独立的:您既可以不使用,也可以单独使用,也可以同时使用。它们可以防止不同类型的攻击。两者都使用是最好的课程。
重要的是要注意,作为一个小点,有时编写包含动态 SQL 的存储过程很有用。在这种情况下,输入参数化的事实并不能自动防御 SQL 注入。这似乎是一个相当明显的观点,但我经常遇到一些人认为因为他们的输入是参数化的,所以他们可以不再担心 SQL 注入。
您是对的,SQL 参数不是可执行代码,因此您无需担心。
但是,您仍然应该进行一些验证。例如,如果您期望 varchar(10) 并且用户输入的内容比这更长,那么您最终会遇到异常。