如何防止SQL (mySQL)注入通过普通转义(不使用准备语句)


How to prevent SQL (mySQL) Injection through plain escaping (not using prepared statements)

首先,让我们弄清楚一件事,虽然我确定这不是sql注入的唯一解决方案,但准备好的语句更好,更安全……这是理所当然的。

所以我们不要再争论它了,因为我只需要探索转义选项并针对用户输入而不是语句。

(一点背景故事)我有一个巨大的应用程序,有很多基本的SQL语句,我需要在短时间内使"更安全"。将所有语句转换为PDO是一项艰巨的任务,它需要的资源在这种情况下是不可用的。

但是好的是,在应用程序中有一个钩子,其中所有传入的$_GET/$_POST在脚本中作为普通变量可用之前都要经过一个函数…(eg.globalize($_POST))

所以我希望瞄准这个功能,而不是专注于"清理"用户输入…

我很好地掌握了SQL注入技术,以及它的基本概念,比如:1)只要在语句中涉及用户输入,攻击者就有机会2)主要任务是在攻击者的输入中通过简单的单引号或双引号作为字符串或字符代码来打破您的语句引用。3)转义很好地防止SQL注入,除非数据库字符编码能够准备好那些讨厌的非法字符串的多字节表示,而基于脚本的转义忽略了它。

根据上述前提,如果:

1)我所有的SQL语句都遵循一个标准,即用户输入总是使用单引号,因此我不再需要猜测我需要转义的引号类型(单引号)

2)所有用户输入(POST/GET)都要经过一个函数(例如;Globalize())基本上是addslashes()并将每个变量

全球化

3)这是一个内部网应用程序,脚本可以知道数据库编码支持。

问题:在上述情况下,目前可用的威胁是什么?我们如何处理这些威胁?

…我个人正在考虑简单地向globalize()函数添加例程,类似于mysql_real_escape_string()。或者"调整"SQL语句以使用mysql_real_escape_string(),因为这比在每个SQL查询上编写语句更容易/更快。

PS当然,这个脚本可能永远不会像准备好的语句那样安全,但我只需要让它对大多数攻击者来说足够困难(不要指望100%的防弹,因为它不值得)

使用

mysql_real_escape_string($link,$non_escaped_string);

请看这里:http://php.net/manual/en/mysqli.real-escape-string.php

虽然它可能工作得很好,但存在一些可能的问题。

如果你使用addslashes,那么有潜在的漏洞,因此对于MySQL mysql_real_escape_string()通常更好。mysql_real_escape_string()中有一个潜在的缺陷(它也适用于pdo的默认使用),但这是如此深奥,您几乎必须尝试使您的代码对基于它的攻击开放。

更大的问题是,您的用户输入可能在具有不同字符集的不同数据库上使用。因此,您应该指定到将要使用转义字符串的数据库的链接。如果没有指定,则将使用最后打开的链接的详细信息。如果没有链接已经被使用,那么它将尝试用一些默认的连接参数连接自己,结果可能是不可预测的。

如果您只是转义所有的$_POST/$_GET/$_REQUEST数组(请记住$_COOKIES数组也可能被恶意用户更改),那么您可能会在脚本第一次加载时进行转义,此时您不太可能连接到适当的数据库。

进一步的问题是,您正在处理的一些代码(并且您似乎没有时间详细处理)必然已经转义了输入数据。因此,您将获得双重转义,并得到奇怪的结果。相关的(但不太可能是问题)是转义数字字段