针对sql注入的'is_numeric'有多安全

时间:2013-09-05 21:03:57

标签: php sql security oracle10g sql-injection

我使用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...
}

所以,我想我真正要问的是,如果其中一个代码块真正比另一个更安全


编辑:对不起,我没有提前说明,但我使用的是oracle 10g数据库,而不是mysql。使用oci_connect();

3 个答案:

答案 0 :(得分:9)

为什么要通过这些问题询问如何清理输入,以便从外部数据构建S​​QL语句? 从外部数据构建S​​QL语句很危险。

不要浪费你的时间来担心你如何能想出另一个想到“解决方案”的中途,停下来穿上你的大程序员裤子并开始使用准备好的语句和绑定变量。

这是一个很棒的答案,可以帮助您入门: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']);