Подтвердить что ты не робот

Какие символы на самом деле способны вызвать SQL-инъекцию в mysql

Мы все знаем, что мы должны использовать подготовленные инструкции или соответствующие правила замены/форматирования, чтобы предотвратить внедрение SQL в наших приложениях.

Однако, взглянув на список символов символов mysql, я заметил, что он включает в себя следующие символы:

  • \0 Символ ASCII NUL (0x00).
  • \ "Символ одиночной кавычки (" ").
  • \ "Символ двойной кавычки (" "").
  • \b Обратный символ.
  • \n Символ новой строки (linefeed).
  • \r Символ возврата каретки.
  • \t Символ табуляции.
  • \Z ASCII 26 (Control + Z). См. Примечание, следующее за таблицей.
  • \\Символ обратной косой черты ( "\" ).
  • \%Символ "%".
  • \_ Символ "_".

Теперь, когда символы% и _ должны быть экранированы, чтобы предотвратить включение нежелательных групповых символов в операторы LIKE, а в то время как '(одинарная кавычка),\(обратная косая черта) и "(двойная кавычка), все должны чтобы избежать инъекции произвольного SQL - может ли любой из этих других персонажей, не привязанных к экрану, привести непосредственно к уязвимости SQL-инъекции, которая иначе не присутствовала бы? Есть ли у кого-нибудь реальные примеры такого эксплойта?

Предположим, что мы строим наш запрос следующим образом:

SELECT * FROM users WHERE username='$user'

Есть ли какое-либо значение для $user, где единственными лимитированными символами без символов являются \b (backspace),\0 (NUL),\n (новая строка),\r (строка),\t (вкладка) или \Z (Ctrl + Z), который позволяет вводить произвольный SQL в этот запрос?

4b9b3361

Ответ 1

Учитывая приведенные ниже строки из mysql_real_escape_string():

MySQL требует только того, что обратная косая черта и символ кавычки, используемый для указания строки в запросе, будут экранированы. mysql_real_escape_string() цитирует другие символы, чтобы облегчить их чтение в файлах журналов.

SQL-инъекция в MySQL не должна быть возможна только с помощью этих специальных символов: \b \0 \n \r \t \Z.

Однако в руководстве String Literals указано следующее, но указанные причины (или нет) не относятся к SQL-инъекции:

Если вы хотите вставить двоичные данные в строковый столбец (например, столбец BLOB), вы должны указать определенные символы путем escape последовательности. Обратная косая черта ( "\" ) и символ кавычки, используемый для цитирования строки, должны быть экранированы. В некоторых клиентских средах также может возникнуть необходимость избежать NUL или Control + Z. Клиент mysql усекает цитируемые строки, содержащие символы NUL, если они не экранированы, а Control + Z может быть выбран для END-OF-FILE в Windows, если он не экранирован.

Кроме того, в простом тесте, независимо от погоды, вышеупомянутые специальные символы экранированы или нет, MySQL дал одинаковые результаты. Другими словами, MySQL даже не возражал:

$query_sql = "SELECT * FROM `user` WHERE user = '$user'";

Вышеупомянутый запрос работал аналогично для неэкранированных и экранированных версий этих выше перечисленных символов, как указано ниже:

$user = chr(8);     // Back Space
$user = chr(0);     // Null char
$user = chr(13);    // Carriage Return
$user = chr(9);     // Horizontal Tab
$user = chr(26);    // Substitute
$user = chr(92) .chr(8);    // Escaped Back Space
$user = chr(92) .chr(0);    // Escaped Null char
$user = chr(92) .chr(13);   // Escaped Carriage Return
$user = chr(92) .chr(9);    // Escaped Horizontal Tab
$user = chr(92) .chr(26);   // Escaped Substitute

Таблица тестов и данные, используемые в простом тесте:

-- Table Structure

CREATE TABLE IF NOT EXISTS `user` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `user` varchar(10) CHARACTER SET utf8 NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB  DEFAULT CHARSET=utf8;

-- Table Data

INSERT INTO `user` ( `user` ) VALUES
( char( '8' ) ),
( char( '0' ) ),
( char( '10' ) ),
( char( '13' ) ),
( char( '9' ) ),
( char( '26' ) );

Ответ 2

Нет таких символов.

В вашем вопросе есть два неправильных утверждения, которые приводят вас к путанице:

  • Мы все знаем, что мы должны использовать... соответствующие правила замены, чтобы предотвратить внедрение SQL в наших приложениях.

Это неверный оператор. Не замена, а форматирование. Это важно. Замены не защищают от инъекций, в то время как форматирование делает. Обратите внимание, что для каждой отдельной части запроса требуется другое форматирование, которое бесполезно для любой другой части. Скажем, есть еще один символ, необходимый для защиты от инъекций - обратная сторона (`). Но вы не указали его, потому что это не имеет никакого отношения к строковым литералам.

  • (одиночная кавычка),\(обратная косая черта) и "(двойная кавычка) все должны быть экранированы, чтобы предотвратить инъекцию

Это ужасно неправильное утверждение. Escaping не мешает инъекциям! Эти символы должны быть экранированы для форматирования строк и не имеют абсолютно никакого отношения к инъекциям. Хотя верно, что правильно отформатированная часть запроса неуязвима для инъекций. Но правда в том, что вам нужно форматировать динамические части запроса только ради этого, следовать правилам синтаксиса - не из-за каких-либо инъекций. И как следствие, ваш запрос будет непроницаем.

Теперь вы можете понять, почему ваше последнее утверждение,

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

ошибочно поставлен:
Правилам строкового форматирования требуются эти символы, а не "уязвимость". Некоторые из них ускользают только для удобства, некоторые - для удобочитаемости, некоторые - из-за очевидной причины выхода из разделителя. Это все.

Чтобы ответить на последние вопросы из комментариев:

Мне действительно нужен ответ на этот вопрос, поскольку PHP mysql_real_escape_string также не цитирует эти литералы.

Опять же: хотя в виду среднего пользователя PHP mysql_real_escape_string() сильно связан с любой пугающей инъекцией, на самом деле это не так. Нет никаких "опасных" персонажей. Ни одного. Есть некоторые служебные персонажи со специальным смыслом. Их нужно избегать в определенных обстоятельствах, в зависимости от контекста.

Таким образом, нет никакой связи между символами, спрятанными этой функцией, и любой "опасностью". В тот момент, когда вы начинаете думать, что цель mysql_real_escape_string() состоит в том, чтобы избежать "опасных" символов, вы действительно становитесь в опасности. Пока вы используете эту функцию только для того, чтобы избежать строк (и делать это безоговорочно) - вы можете считать себя в безопасности (конечно, если вы не забудете также форматировать все другие литералы, используя их соответствующие правила форматирования)

Я хочу знать, может ли символ "%" привести к чем-либо более чем дополнительным результатам в предложении LIKE.

Нет.