显然我的PHP代码中存在SQL注入错误

时间:2011-12-07 02:18:58

标签: php sql-injection

include "../admin/site.php"; // Setup db connection.

$appid = -1;
if (is_string($_GET["id"]))
{
    $id = mysql_real_escape_string($_GET["id"]);
    $sql = "select * from version where id=$id";
    $ver = mysql_query($sql);
    if ($id > 0 && $ver && mysql_num_rows($ver))
    {
        $appid = mysql_result($ver, 0, "AppID");
        $app = DLookUp("apps", "name", "id=$appid");
        $name = mysql_result($ver, 0, "Name");
        $notes = mysql_result($ver, 0, "Notes");
    }
    else $app = "No version by that ID";
}
else $app = "No ID";

/* some html snipped */

if (isset($app) && isset($name))
    echo $app . " v" . $name;
else
    echo "v###";

/* some html snipped */

if (isset($appid))
{
    $url = "/" . DLookUp("apps", "Page", "id=$appid");
    echo "<a href=\"$url\">Up</a> to $app...";
}
if (isset($notes))
    echo $notes;

不知何故,此代码允许某人查看我的数据库的全部内容。我以为mysql_real_escape_string会阻止那种攻击吗?我可以将$ id转换为一个应该解决问题的整数,但是我想知道我在这里做错了什么,所以我不会一直重复我的错误。

5 个答案:

答案 0 :(得分:5)

我认为问题的一部分是你没有在$id周围使用引号,因此攻击者可能会发送id为1 OR 1=1的值,而执行的SQL将是:

select * from version where id=1 OR 1=1

mysql_real_escape_string()只转义NULL,换行符和引号(\ x00,\ n,\ r,\,','和\ x1a),所以如果你不引用变量就没什么用处

答案 1 :(得分:4)

您(至少)需要引用$id,即使该列是整数

select * from version where id="{$id}"

但是,如果使用

供应$ _GET [“id”]
$id = "xxx\" OR 1=1";
select * from version where id="{$id}" <-- this become a vulnerable 
as it eval to
select * from version where id="xxx" OR 1=1

您应该考虑绑定参数:

select * from version where id :=id

或至少进行整数$id = (int)$_GET["id"]的转换,
你想与整数列比较,不是吗? (当$ _GET [“id”]不是整数时强制它为零)

看看这个: -

处理mysql_ *函数时,始终附上数据库链接标识符 (您可能在一个页面中有多个数据库连接)

答案 2 :(得分:1)

mysql_real_escape_string可能无法解释某些多字节编码字符。您的攻击者可能正在使用多字节序列,该序列针对您的数据库特定字符集进行了不正确的转义。

预防注射的最佳方法是使用预先准备好的陈述。

答案 3 :(得分:1)

我对此的看法是有多种可能性:

由于$id周围没有引号,攻击者可能会发送1或1 = 1的id值,执行的SQL将是:

select * from version where id=1 OR 1=1

检查它是否为整数:

if (intval($_GET['id']) > [some condition]) //do something

输入Caste it:

$id = (int) $_GET['id'];

最后但并非最不重要,我会使用prepared statements

<?php
$query = "select * from version where id=?";
$stmt = $dbh->prepare($query);
$stmt->execute(array($_GET['id']);
?>

答案 4 :(得分:0)

我能看到的唯一问题是你的身份

我会检查它是否真的是一个整数。

if (is_int($_GET['id'])) 
{

你可以继续...那将确保你的id真的是一个整数。