Очевидно, в моем PHP-коде есть ошибка SQL-инъекции - PullRequest
4 голосов
/ 07 декабря 2011
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 ]

5 голосов
/ 07 декабря 2011

Я думаю, что отчасти проблема в том, что вы не используете кавычки вокруг $id, поэтому злоумышленник может отправить значение для идентификатора, равное 1 OR 1=1, и выполненный SQL будет:

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

mysql_real_escape_string() экранирует только NULL, символы новой строки и кавычки (\ x00, \ n, \ r, \, ', "и \ x1a), так что это мало поможет, если вы не заключите в кавычки переменную.

4 голосов
/ 07 декабря 2011

Вы (по крайней мере) должны заключить в кавычки $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_ *
(у вас может быть несколько подключений к базе данных на одной странице)

1 голос
/ 07 декабря 2011

Я предполагаю, что существует несколько возможностей:

Поскольку вокруг * 1003 нет кавычек *, злоумышленник может отправить значение для id, равное 1 ИЛИ = 1, и выполненный SQL будет:

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

Проверьте, является ли его целым числом:

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

Тип Примените его:

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

В заключение, но не по значению, я бы использовал подготовленные заявления

<?php
$query = "select * from version where id=?";
$stmt = $dbh->prepare($query);
$stmt->execute(array($_GET['id']);
?>
1 голос
/ 07 декабря 2011

Возможно, что mysql_real_escape_string не сможет учесть определенные многобайтовые кодированные символы.Вероятно, ваш злоумышленник использует многобайтовую последовательность, которая неправильно экранирована для конкретной кодировки вашего БД.

Лучший способ предотвратить инъекцию - использовать подготовленные операторы.

0 голосов
/ 07 декабря 2011

Единственная проблема, которую я мог видеть, - это ваш идентификатор

Я бы проверил, действительно ли оно целое число.

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

Вы можете продолжить ... Это гарантирует, что идентификатордействительно целое число.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...