Безопасен ли этот запрос от внедрения sql?


Скрипт написан на PHP, и в качестве базы данных я использую MySQL. Вот сам сценарий.

$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;) в таблицу.

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

Author: Sam, 2010-06-14

8 answers

Эта конкретная инъекция не будет работать, так как функция 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);
 13
Author: Richard Simões, 2010-06-14 19:35:28

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

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

 4
Author: Lotus Notes, 2010-06-14 19:21:44

В то время как mysql_query позволяет выполнять только один запрос, в целом этот запрос небезопасен. Примером опасного ввода, который может использовать ваш запрос, является:

'); DROP TABLE my_table; --

'); в начале закроет ваш запрос и вставит пустое значение, но позволит выполнять дополнительные запросы после ВСТАВКИ. Затем, после удаления таблицы, -- в конце пометит все остальное, следующее (т. Е. остальная часть вашего запроса) в качестве комментария.

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

 3
Author: Daniel Vandersluis, 2010-06-14 19:22:41

ЕДИНСТВЕННЫЙ способ, которым вы должны обрабатывать небезопасные переменные, - это использовать параметры привязки.

Пожалуйста, прочитайте эту страницу о том, как предотвратить внедрение SQL из bobby-tables.com.

 2
Author: Andy Lester, 2010-06-14 19:27:52

Нет, sprintf не избегает использования контента:

$unsafe_variable = mysql_real_escape_string($_GET["user-input"]);
$sql=sprintf("INSERT INTO table (column) VALUES('%s')",$unsafe_variable);
mysql_query($sql);
 1
Author: Aaron Harun, 2010-06-14 19:22:20
mysql_real_escape_string($unsafe_variable)
 1
Author: Justin K, 2010-06-14 19:22:29

Некоторые люди говорят, что если пользователь назначает;УДАЛИТЬ ТАБЛИЦУ бла-бла; строку переменной $unsafe_variable, она удаляет таблицу.

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

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

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

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

Или

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

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

C.

 1
Author: symcbean, 2010-06-14 19:22:46

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

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

 0
Author: catsby, 2010-06-14 19:24:07