5

我对所有内容都使用 is_numeric,我从用户那里得到的唯一输入是带有学生 ID 号的表格......

我最近在阅读 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();

4

3 回答 3

9

您为什么要回答这些问题,询问如何清理输入以便从外部数据构建 SQL 语句? 从外部数据构建 SQL 语句是危险的。

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

这是一个很棒的答案,可以帮助您入门:如何防止 PHP 中的 SQL 注入?

您还可以查看http://bobby-tables.com/php以获取其他示例。

在我看来,您仍然可以使用 Oracle 执行准备好的语句和绑定变量:http: //php.net/manual/en/function.oci-bind-by-name.php或通过 PDO http://php.net/手册/en/pdostatement.bindparam.php

于 2013-09-05T21:09:52.783 回答
8

根据经验,仅检查数据是不够安全的,您应该始终在使用数据之前对其进行预处理。

假设您不了解其工作原理的所有内部结构is_numeric。或者你不知道它的逻辑或它的实现将来是否会改变。或者你没有对它进行足够的测试。或者它的文档缺少一些非常具体但重要的说明。

总而言之,有一天它可能is_numeric返回TRUE,但数据在 SQL 中使用是不安全的。

但是,如果您在检查输入数据后没有停止,而是根据输入创建了一条新数据,那么您肯定可以说出您的这些数据是什么,不是什么。在这种情况下,它绝对是一个整数值,仅此而已。(虽然is_numeric也适用于浮点值,但你知道吗?你打算这样做吗?不?)

再举一个例子:如果您的输入是十六进制、八进制或二进制表示法的字符串,is_numeric将返回TRUE,但您的数据库甚至可能不支持这种特定表示法(例如,MySQL 不支持八进制),因此您不会得到预期的结果.

于 2013-09-05T22:20:54.907 回答
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']);
于 2013-09-05T21:12:30.803 回答