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 на целое число, которое должно исправить проблему, но я хочу понять, что я сделал неправильно здесь, поэтому я не повторяю свою ошибку.
Я думаю, что часть проблемы заключается в том, что вы не используете кавычки вокруг $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), поэтому это мало помогает, если вы не приводите эту переменную.
Вы (по крайней мере) должны указывать $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_ *
(у вас может быть несколько соединений с базой данных на одной странице)
Возможно, mysql_real_escape_string
не сможет учесть определенные многобайтовые закодированные символы. Вероятно, ваш злоумышленник использует многобайтную последовательность, которая ненадлежащим образом экранирована для конкретной кодировки вашего db.
Лучший способ предотвратить инъекцию – это использование подготовленных заявлений.
Я считаю, что существует множество возможностей:
Поскольку в $id
нет кавычек, злоумышленник может отправить значение для id, равное 1 OR 1 = 1, а выполняемый SQL:
select * from version where id=1 OR 1=1
Проверьте, есть ли целое число:
if (intval($_GET['id']) > [some condition]) //do something
Тип Caste it:
$id = (int) $_GET['id'];
Наконец, но не в последнюю очередь, я бы использовал подготовленные заявления
<?php $query = "select * from version where id=?"; $stmt = $dbh->prepare($query); $stmt->execute(array($_GET['id']); ?>
Единственная проблема, которую я видел, – это ваш идентификатор
Я бы проверял, действительно ли это целое число.
if (is_int($_GET['id'])) {
Вы можете продолжить … Это заверит вас, что идентификатор действительно является целым числом.