Является ли этот запрос безопасным от SQL-инъекции?

script находится в PHP, а в качестве DB я использую MySQL. Вот сам script.

$unsafe_variable = $_GET["user-input"];
$sql=sprintf("INSERT INTO table (column) VALUES('%s')",$unsafe_variable);
mysql_query($sql);

Некоторые говорят, что если пользователь присваивает строку ;DROP TABLE blah; переменной $unsafe_variable, она удаляет таблицу.

Но я попробовал этот пример,

http://localhost/test.php?user-input=DROP%20TABLE%20my_table 

Но он не удалял таблицу, а вместо этого вставил новую строку (;DROP TABLE blah;) в таблицу.

Может ли кто-нибудь объяснить мне, как можно атаковать этот script с помощью SQL-инъекций?

Ответ 1

Эта конкретная инъекция не будет работать, поскольку функция PHP mysql_query допускает только один запрос на вызов. Однако, если column имеет первичный или уникальный ключ:

$unsafe_variable = "admin') ON DUPLICATE KEY UPDATE password=MD5(CONCAT('knownsalt', 'newpassword'))#";

Лучше использовать функцию с длинной ветвью mysql_real_escape_string:

$sql=sprintf("INSERT INTO table (column) VALUES(%s)",
             mysql_real_escape_string($unsafe_variable));
mysql_query($sql);

Ответ 2

mysql_query() не позволяет выполнять несколько запросов в одной функции. Таким образом, вы не можете ВСТАВИТЬ, а затем ПОСМОТРЕТЬ таблицу. Но вы не должны полагаться на это как на "безопасность". Вместо этого используйте параметризованные запросы. Ознакомьтесь с библиотекой PHP PDO.

Однако они могли бы изменить что угодно, например, SELECTing поле пароля из другой таблицы в качестве подзапроса для размещения в этой таблице, чтобы они могли просматривать хэш.

Ответ 3

Пока mysql_query разрешает только один запрос, в общем случае этот запрос небезопасен. Пример опасного ввода, который будет использовать ваш запрос:

'); DROP TABLE my_table; --

'); в начале закроет ваш запрос и введет пустое значение, но позволит выполнять дополнительные запросы после INSERT. Затем после отбрасывания таблицы -- в конце будет отмечать все остальное, следующее (т.е. Остальную часть вашего запроса) в качестве комментария.

Чтобы безопасно подготовить ввод для использования в запросе, используйте mysql_real_escape_string.

Ответ 5

Нет, sprintf не избегает использования содержимого:

$unsafe_variable = mysql_real_escape_string($_GET["user-input"]);
$sql=sprintf("INSERT INTO table (column) VALUES('%s')",$unsafe_variable);
mysql_query($sql);

Ответ 6

mysql_real_escape_string($unsafe_variable)

Ответ 7

Некоторые люди говорят, что если пользователь назначает: DROP TABLE blah; string к переменной $unsafe_variable удаляет таблицу.

По-видимому, это не так, но если вы не понимаете, почему, тогда вы не можете определить, безопасен ли ваш код. Собираетесь ли вы опубликовать каждую строку здесь, чтобы проверить, безопасно ли это?

Не вдаваясь в подробное объяснение того, что делает вышеприведенный код и как его нарушить (SQL-инъекция уже хорошо документирована в другом месте - попробуйте Google для начала), вы должны ВСЕГДА гарантировать, что любые данные, выходящие из вашего кода PHP, будут правильное представление о том, куда он идет.

Для базы данных MySQL это означает:

1) используйте вывод mysql_real_escape_string (и убедитесь, что вы передали правильный дескриптор ресурса)

или

2) используйте привязку параметров.

Правильное обсуждение атак с инъекциями кода может легко заполнить несколько сотен страниц - немного, чтобы ответить в S.O. запрос.

С.

Ответ 8

Я думаю, что пример, который вам нужно попробовать, это http://localhost/test.php?user-input=';DROP%20TABLE%20my_table'

'); закрывает сегмент values('%s, а затем выдает новую команду drop table...