По-видимому, в моем PHP-коде есть ошибка SQL-инъекции

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 на целое число, которое должно исправить проблему, но я хочу понять, что я сделал неправильно здесь, поэтому я не повторяю свою ошибку.

Related of "По-видимому, в моем PHP-коде есть ошибка SQL-инъекции"

Я думаю, что часть проблемы заключается в том, что вы не используете кавычки вокруг $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_real_escape_string () ПОЛНОСТЬЮ защищает от SQL-инъекции?

И всегда включайте идентификатор ссылки базы данных при работе с функцией 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'])) { 

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