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

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

однако, взглянув на список символьных литералов MySQL, я заметил, что он включает следующие символы:

  • ASCII NUL (0x00) характер.
  • ' одиночная кавычка (') характер.
  • " двойной цитата (") характер.
  • b символ backspace.
  • n символ новой строки (linefeed).
  • r символ возврата каретки.
  • t символ табуляции.
  • Z ASCII 26 (Ctrl+Z). См. Примечание после таблицы.
  • обратная косая черта () характер.
  • % A % характер.
  • _ A _ символ.

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

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

SELECT * FROM users WHERE username='$user'

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

2 ответов


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

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

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

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

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

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

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

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

$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' ) );

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

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

  1. все мы знаем, что мы должны использовать ... соответствующие правила замены для предотвращения SQL-инъекций в наших приложениях.

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

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

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

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

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

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

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

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

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

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

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

нет.