我知道参数化查询,但我有几个旧网站,我已经使用这种方法来清理用户输入:
<?
mysql_query( sprintf( 'SELECT col1 FROM table1 WHERE id = %d', $tainted ) );
?>
请注意,%d
周围没有引号。 $tainted
是否有任何可能导致此类查询出现意外结果的值?提出语法错误很容易,但我并不太在意。
我对类似的UPDATE和DELETE查询使用了相同的方法。我是否应该回过头来修复所有旧查询,或者这里没有漏洞?
答案 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转义所有变量。
希望有所帮助。