我想通过检查SQL查询来检测可能的SQL注入。我正在使用PDO和准备好的声明,所以希望我没有被某人攻击的危险。但是,我想检测的是输入/生成的查询字符串可能成为危险查询的可能性。例如,我的应用程序(正确(永远不会生成"1=1"查询,因此我可以检查生成的查询字符串,并标记生成该查询的用户/IP。与"删除表"相同,但也许我只能通过循环输入数组来检查;或者也许我应该再次检查生成的查询。我正在使用MySQL,但也赞赏其他驱动程序的模式。
我已经阅读了正则表达式来检测SQL注入,一些评论正朝着这个方向发展。在我的帮助下,我正在为很少使用英语作为输入的用户开发,因此查询上的简单/drop/匹配可能足以记录用户/查询以供进一步检查。我在研究SQL注入时发现的一些模式是:
- 句子中间的分号 - 尽管这可能很常见
- 双破折号/井号,用于注释查询的其余部分
- 在值的开头和结尾使用引号
- 使用十六进制(我的目标用户在表单中输入 0x 的机会很小到很低(
- declare/exec/drop/1=1(我的应用不应生成这些值(
- HTML 标记(来自预期用户/用例的可能性低(
- 等。
通过在生成查询字符串之前循环输入值,可以更轻松地检测上述所有内容,因为它们尚未转义。但是我错过了多少?(很多,我猜(我应该检查任何其他模糊的模式吗?如何检查生成的查询?可能出现的任何模式?
tl;dr:什么模式来匹配SQL查询(MySQL(来检查可能的注入?我正在使用带有预准备语句和值绑定的 PDO,因此检查用于日志记录/警报目的。
在我的店里,我们有两个规则。
- 始终在 SQL 查询中使用参数。
- 如果由于某种原因无法遵循规则 1,则必须清理放入查询的每个数据,要么使用整数参数
intval()
,要么使用适当的函数根据字符串变量的应用程序数据类型对其进行清理。例如,人名可以是Jones
或O'Brien
或St. John-Smythe
,但除了撇号'
、连字符-
、空格或点之外,永远不会有特殊字符.
产品编号可能只包含字母或数字。等等。
如果 2 太难,请遵循规则 1。
我们检查代码以确保我们正在执行这些操作。
但是我错过了多少?
你猜对了。创建一个巨大的黑名单不会让你的代码免疫。这种方法已成为历史。其他问题遵循同样的想法。
您最好的选择是:
- 验证输入数据(输入不一定来自外部方(
- 使用预准备语句。
几步,但防弹。
不可能。
你将在军备竞赛中度过余生——你建立防御,他们制造更好的武器,然后你建立防御,等等,等等。
- 可能可以编写一个需要 24 小时才能运行的"简单"
SELECT
。 - 除非您锁定表,否则他们可以查看加密的密码并使用
root
登录重新攻击。 - 如果您允许任何类型的字符串,则处理各种引号组合将是一个挑战。 使用
- 半有效的 utf8 字符串可以做一些令人讨厌的事情。
- 那么
SET
声明呢。 - 和
LOAD DATA
. - 和存储的过程。
相反,请确定允许的最小查询集,然后将其参数化,以便可以单独检查或转义这些部分。 然后生成查询。