我使用is_numeric作为一切,我从用户那里得到的唯一输入是一个带有学生证号码的表格....
我最近正在阅读SQL注入,并想知道是否需要采取以下预防措施?
目前我有:
if(is_numeric($_POST['sid']){
$sid = $_POST['sid'];
$query = "select * from student where sid='".$sid."'";
// More Code...
}
我读过的内容更安全
if(is_numeric($_POST['sid']){
$sid = (int) $_POST['sid'];
$query = "select * from student where sid='".$sid."'";
// More Code...
}
一个版本真的比另一个版本更安全吗?如何绕过'is_numeric'?
另外,这比我目前的安全性还要低吗?
if(is_numeric($_POST['sid']){
$query = "select * from student where sid='".$_POST['sid']."'";
// More Code...
}
所以,我想我真正要问的是,如果其中一个代码块真正比另一个更安全
答案 0 :(得分:9)
为什么要通过这些问题询问如何清理输入,以便从外部数据构建SQL语句? 从外部数据构建SQL语句很危险。
不要浪费你的时间来担心你如何能想出另一个想到“解决方案”的中途,停下来穿上你的大程序员裤子并开始使用准备好的语句和绑定变量。
这是一个很棒的答案,可以帮助您入门:How can I prevent SQL injection in PHP?
您还可以查看http://bobby-tables.com/php了解其他示例。
在我看来,您仍然可以使用Oracle执行预准备语句和绑定变量:http://php.net/manual/en/function.oci-bind-by-name.php或通过PDO http://php.net/manual/en/pdostatement.bindparam.php
答案 1 :(得分:6)
根据经验,仅仅检查数据是不够安全的,在使用数据之前,您应该始终预处理数据。
假设您不知道所有 is_numeric
如何工作的内部结构。或者您不知道其逻辑或其实现是否会在将来发生变化。或者你没有足够严重地测试它。或者它的文档缺少一些非常具体但重要的注释。
总而言之,有一天可能会发生is_numeric
返回TRUE
,但数据在SQL中使用是不安全的。
但是,如果您在检查输入数据后没有停止,而是根据输入创建了新的数据,您可以肯定地说明您的数据是什么以及它不是什么。在这种情况下,它绝对是一个整数值,没有别的。 (虽然is_numeric
也适用于浮动值,你知道吗?你有意吗?不是吗?)
另一个例子:如果您的输入是十六进制,八进制或二进制表示法的字符串,is_numeric
将返回TRUE
,但您的数据库可能甚至不支持此特定表示法(MySQL不支持例如,八进制),所以你不会得到预期的结果。
答案 2 :(得分:5)
我不赞同任何一个版本。您应该使用的是使用PDO或mysqli正确参数化的查询。例如:
$query = "SELECT * FROM student WHERE sid = ?";
$stmt = $pdo->prepare($query);
$stmt->execute(array($_POST['sid']));
在这种情况下,漏洞将在数据库访问级别处理,而不是在应用程序级别处理。这可能看起来不是什么大问题,但是有人可能会将查询移到if
语句之外并且不正确地使用查询(你可能会认为有人也可以重写一个易受攻击的查询,但这可能会少一些故障)。
您还可以将值与类型绑定。
$stmt = $pdo->prepare($query);
$stmt->bindValue(1, (int)$_POST['sid']);