0

我确实知道参数化查询,但我有几个旧网站使用这种方法来清理用户输入:

<?
mysql_query( sprintf( 'SELECT col1 FROM table1 WHERE id = %d', $tainted ) );
?>

请注意,周围没有引号%d。是否有任何价值$tainted可能导致此类查询产生意外结果?很容易给出语法错误,但我不太在意。

我对类似的 UPDATE 和 DELETE 查询使用了相同的方法。我应该费心回去修复所有旧查询,还是这里没有漏洞?

4

4 回答 4

4

不,这不是漏洞。

但这是一个潜在的漏洞:如果某个维护程序员决定执行一个小的更改并且忘记了变量可能被污染,或者如果变量的数据类型从整数更改为字符串(以及说明符为%s) - 那么会有麻烦。

最好一开始就不要去那里(但从实际的角度来看,加强对遗留代码的防御是否值得也并不明显)。

于 2012-08-02T22:01:12.607 回答
3

要回答您的问题,以您提供的方式使用 sprintf 应该避免任何 sql 注入,因为通过 %d 将任何非 int 值转换为十进制值只会取值为 0:

$ -> php -r "echo sprintf('update table where id = %d', 'drop databases');"
update table where id = 0

但是,如果我没有试图说服您使用PDO API,更具体地说,是使用准备好的语句,那么我将是失职的。我相信mysqli API 也有准备好的语句,但我从未使用过它们,只使用过 PDO 准备,或者像 Doctrine 或 Propel 这样的 ORM。

于 2012-08-02T22:05:19.057 回答
1

它作为输入看起来足够安全,但从用户体验的角度来看,它肯定是不可取的,因为如果输入与 id 属性所需的参数不匹配,您将无法向用户提供详细信息.

于 2012-08-02T22:00:18.257 回答
0

理论上,它不应该是易受攻击的,因为sprintf()如果它不是数字,就不会插入变量。

然而,这并不意味着它是正确的。它仍然可能导致可能破坏您的代码的错误。

无论这是否易受攻击,我都强烈建议mysql_xx()完全放弃这些功能。

旧的 MySQL 库已被弃用(请参阅PHP 手册页上的注释),建议切换到 PDO 或mysqli_xx库。

PDO 和 MySQL 都带有一个名为 Prepared Queries 的功能,它完全可以完成您在此处尝试实现的功能,并且是比sprintf()此类事情更好的解决方案。也无需为 SQL 转义所有变量。

希望有帮助。

于 2012-08-03T20:13:37.480 回答