是否可以使用简单的正则表达式检测 100% 的 SQLi?

信息安全 sql注入 身份证 检测 正则表达式
2021-08-14 19:31:29

我想知道是否可以使用简单的正则表达式检测 100% 的可能 SQLi 攻击。

换句话说,以非常简单的 PHP 代码为例:

if (preg_match("/select/i", $input)) {
    attack_log("Possible SELECT SQLi detected.")
}

问题是:

  • 该正则表达式会捕获所有可能使用 SELECT 的 SQLi 攻击吗?如果没有,是否可以更改该正则表达式以便检测所有依赖 SELECT 的注入?
  • 是否可以将该正则表达式更改为使其能够捕获所有可能的 SQLi,因此不仅是 SELECT 语句,而且还有所有其他语句?恐怕要实现这一点,我需要将所有可能的 SQL 关键字添加到正则表达式,包括“AND”和“OR”。
  • 假设通过尝试匹配所有可能的 SQL 关键字来检测所有 SQLi 是不可能或不可行的,是否有有限的关键字子集可以让我检测到绝大多数可能的攻击?
4个回答

SQLi 的关键字过滤不是一个好的技术。绕过它的方法太多了。

例如,疯狂的事情sel/**/ect可能会奏效。或者玩游戏substr()然后是EXEC('SEL' + 'ECT 1').

很多关于如何绕过常见过滤技术的指南。

但是随后您可能会问是否有要过滤的超集(例如selectand/**/substrand EXEC),但是列表变得非常非常长,您可能仍然无法获得完整的列表。

更好的方法是了解可接受输入的范围并保护这些输入,或者通过适当的设计使其无效使用 SQLi。

由于每个 SQL 注入(根据定义)都是有效的 SQL,并且由于 SQL 是一种上下文无关语言(source),因此(再次,根据定义)没有正则表达式能够匹配 SQL 注入,并且尝试这样做可能会给出结果类似这样

正如几乎每条评论所说,为工作使用正确的工具。在这种情况下,它是一个准备好的语句。

从技术上讲,这是完全可能的(尽管这样做也会使数据库变得无用):

  • .+确实会检测到任何可能的SQLi。

但是,它也会检测到任何进行正常查询(或任何文本)的尝试,从而使数据库完全无用

您同样可以说关闭数据库可以防止 SQLi。确实如此,但它也使数据库无法达到其预期目的。

使用准备好的语句或参数化查询。它们的存在是为了解决这个问题。

我想知道是否可以使用简单的正则表达式检测 100% 的可能 SQLi 攻击。

您以这种方式提出问题的事实表明您正在错误地考虑问题。

SQL 注入不是数据中的漏洞。这是处理该数据的应用程序代码的一个漏洞。

例如:现在我在网站的文本区域中输入“SQL 注入”!我可以输入类似' -- DROP TABLE Users; 就在这儿!我的回答是 SQL 注入攻击吗?当然不是。

现在,您可以争辩说您正在尝试做的是检测尝试的SQL 注入攻击。但是现在您需要确定某些输入的意图如果我在字段中输入一个单引号,这是一个错字还是一次尝试的 SQL 注入攻击?你能检测到我 100% 的意图吗?当然不是。

从根本上说,尝试识别可能的攻击意味着您的检测率永远不会是 100%。

由于 SQL 注入漏洞只存在于代码中,而不存在于数据中,因此任何只考虑数据的分析充其量都存在非常大的误报率。您设计的任何可能匹配所有实际攻击流量的解决方案也会将大量流向本网站以及许多其他网站的合法流量解释为“攻击”,而并非有意进行此类攻击。