sprintf('%d',$ tainted)在SQL查询中是一个漏洞吗?

时间:2012-08-02 21:48:50

标签: php mysql sql-injection validation

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

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

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

我对类似的UPDATE和DELETE查询使用了相同的方法。我是否应该回过头来修复所有旧查询,或者这里没有漏洞?

4 个答案:

答案 0 :(得分:4)

不,这不是一个漏洞。

但它是潜在的漏洞:如果某个维护程序员决定执行一个小的更改并忘记变量可能被污染,或者变量的数据类型从整数变为字符串(和<{1}}的指定者 - 即将出现问题。

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

答案 1 :(得分:3)

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

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

但是如果我没有试图说服你使用PDO API,更具体地来说,prepared statements,那将是我的疏忽。我相信mysqli API也有准备好的声明,但我从未使用过它们,只使用过PDO准备,或者是一个ORM,如Doctrine或Propel。

答案 2 :(得分:1)

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

答案 3 :(得分:0)

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

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

无论这是否容易受到攻击,我都强烈建议您完全不再使用mysql_xx()功能。

旧的MySQL库已被弃用(请参阅the PHP manual pages上的说明),建议切换到PDO或mysqli_xx库。

PDO和MySQL都有一个名为Prepared Queries的功能,它完全符合您在此处尝试实现的功能,并且比sprintf()更好地解决了这类问题。不需要为SQL转义所有变量。

希望有所帮助。