没有参数化查询在PHP中防止SQL注入?

时间:2015-10-02 08:32:36

标签: php mysql security sql-injection

我知道这个话题已经被解决了,但我希望社群能够就我们的网络应用程序中的安全性提供一些反馈。

我们有标准的LAMP堆栈Web应用程序,其中包含使用mysqli_query执行的大量数据库查询。这些查询没有参数化,目前使用addslashes进行了一些天真的输入转义。

我的任务是让这个系统更安全,因为我们很快就会进行渗透测试。上述权力知道参数化查询是使系统更安全的方法,但是他们不想花时间和精力重写应用程序中的所有查询,还要改变我们必须制定的框架它们都能正常工作。

所以基本上我在问我的选择在哪里?

我已在输入上运行mysqli_real_escape_string。我设置了一个过滤器,它不允许传递SELECT,WHERE,UNION这样的单词,我想这会使它更安全。我知道mysqli_query只允许一次运行一个查询,因此在那里有一些安全性(从连接更新到选择的结尾)。

我还有其他选择吗?

编辑:我应该补充一点,如果有人能够提供一个攻击的例子,如果没有参数化查询这也是有帮助的,这是完全不可避免的。我们有一个查询,如下所示:

SELECT
pl.created
p.LoginName,
pl.username_entered,
pl.ip_address
FROM loginattempts pl
LEFT JOIN people p ON p.PersonnelId = pl.personnel_id
WHERE p.personnelid = $id
AND pl.created > $date1
AND pl.created < $date2

我已经将UNION查询替换为$ id UNION SELECT * FROM p WHERE 1 = 1类的东西,我可以通过不允许SELECT / UNION来防止这种情况,但是我确信还有无数其他类型的攻击这是我无法想到的。有人可以提出更多建议吗?

更新

我已经确信我们需要将查询重写为参数化语句。他们估计可能需要几个月但是必须要做。赢得。我想?

UPDATE2

不幸的是,我无法说服我们需要将所有查询重新写入参数化查询的权力。 我们提出的策略是测试每个输入如下:

如果用户提供输入is_int,则将其强制转换为。 实数相同。 对字符数据运行mysqli_real_escape_string。 将查询中的所有参数更改为带引号的字符串,即

WHERE staffName = ' . $blah . '

根据this回答,我们100%安全,因为我们不会随时更改字符集,并且我们始终使用带有latin1字符集的PHP5.5。

更新3

这个问题已被标记为重复,但在我看来,问题仍未得到回答。根据更新号2,我们发现一些强烈意见认为mysqli_real_escape字符串函数可以防止攻击,并且显然是100%安全&#34;。从那以后,没有提供任何好的反驳论据(即证明攻击可以在正确使用时击败它)。

2 个答案:

答案 0 :(得分:7)

  • 检查每个用户输入的数据类型以及使用正则表达式的应用程序(黄金法则是:永远不会信任用户输入)
  • 使用预备陈述
  • 认真:准备好的陈述:)

它的工作量很大,特别是如果您的应用程序状况不佳(就像您的情况似乎如此),但这是获得良好安全级别的最佳方式

另一种方式(我建议反对)可以使用mod_security或WAF进行虚拟补丁来过滤掉注入尝试但首要的是:尝试编写健壮的应用程序 (虚拟补丁似乎是解决问题的一种懒惰方式,但实际上需要进行大量工作和测试,而且应该只在已经很强大的应用程序代码之上使用)

答案 1 :(得分:6)

  

我还有其他选择吗?

没有。没有任何外部措施,例如你试图实施的措施,已被证明是有帮助的。您的网站仍然容易受到攻击。

  

我在输入

上运行了mysqli_real_escape_string

恭喜,您刚刚彻底改造了臭名昭着的magic_quotes功能,该功能被证明是无用的,现在被驱逐出语言。

JFYI,mysqli_real_escape_string与SQL注入完全无关。

此外,将它与现有的addslashes()调用相结合,您可以通过将数据加倍来破坏数据。

  

我已经设置了一个过滤器,我想它会更安全。

不是。 SQL注入不是要添加一些单词。

此外,这种方法被称为&#34;黑名单&#34;它被证明基本上是不可靠的。黑名单基本上是不完整的,无论有多少&#34;建议&#34;你可以得到。

  

我知道mysqli_query只允许一次运行一个查询,所以那里有一些安全性

没有。 SQL注入与添加另一个查询无关。

为什么我将此问题作为副本关闭&#34;如何防止PHP中的SQL注入?&#34;?

因为这些问题是相互排斥的,并且不能在同一网站上共存。

如果我们同意,唯一正确的答案是使用准备好的陈述,那么一个问题就会问:&#34;我如何使用没有准备好的陈述进行保护&#34;没什么意义。

与此同时,如果OP设法迫使我们给出他们迫切想要的肯定答案,那么它将使另一个问题过时。如果没有它们一切都好的话,为什么要使用准备好的陈述呢?

此外,这个特殊问题也过于本地化。它寻求的不是洞察力,而是借口。只有OP个人才有借口。借口让他们使用一种被证明是不安全的方法。虽然它取决于他们,但这使得这个问题对社区来说基本上没用。