Что это за строка?

Строка )))) AND EXTRACTVALUE(7821,CONCAT(0x7e,((SELECT (ELT(7821=7821,1)))),0x7e))-- - — это классический пример error-based SQL-инъекции для СУБД MySQL. Она предназначена для внедрения в уязвимый SQL-запрос с целью заставить сервер вывести данные через сообщение об ошибке. Подобные конструкции часто встречаются в отчётах сканеров уязвимостей и в логах веб-серверов.

Разбор по частям

1. Закрывающие скобки ))))

Начинается строка с четырёх закрывающих скобок. Они нужны, чтобы «закрыть» ранее открытые скобки в исходном SQL-запросе. Если запрос содержит вложенные функции или условия, атакующий добавляет скобки, чтобы синтаксис остался корректным и инъекция сработала.

2. AND

Оператор AND присоединяет наше условие к существующему выражению WHERE. Это позволяет внедрить дополнительную логику, не нарушая структуру запроса.

3. EXTRACTVALUE(7821, ...)

EXTRACTVALUE — это функция MySQL, которая извлекает значение из XML-строки. Синтаксис: EXTRACTVALUE(XML_document, XPath_expression). Если XPath-выражение некорректно, MySQL выбрасывает ошибку, содержащую переданный XPath. Именно это и используется для вывода данных.

Первым аргументом здесь стоит число 7821. Оно не является XML-документом, но это не важно — ошибка возникнет на втором аргументе.

4. CONCAT(0x7e, ..., 0x7e)

CONCAT объединяет строки. 0x7e — это шестнадцатеричное представление символа ~ (тильда). Тильда используется как маркер, чтобы в сообщении об ошибке было легко найти выведенные данные. То есть результат подзапроса будет обёрнут в ~...~.

5. (SELECT (ELT(7821=7821,1)))

Внутри CONCAT находится подзапрос (SELECT (ELT(7821=7821,1))). Разберём его:

  • 7821=7821 — всегда истинное условие (1).
  • ELT(N, str1, str2, ...) — функция, возвращающая N-ю строку из списка. Здесь список состоит из одного элемента 1, а N равно 1. Значит, ELT(1,1) вернёт 1.

Таким образом, подзапрос возвращает строку '1'. В реальной атаке вместо ELT(7821=7821,1) могло бы быть что-то вроде ELT(1,version()) или ELT(1,database()), чтобы вытащить версию СУБД или имя базы данных. Но в данном примере это просто проверка, что инъекция работает: если приложение уязвимо, оно вернёт ошибку с текстом, содержащим ~1~.

6. Комментарий -- -

В конце стоит -- -. В MySQL -- начинает комментарий до конца строки, но только если после него есть пробел. Символ - после пробела нужен, чтобы обойти некоторые фильтры и гарантировать, что остаток оригинального запроса будет закомментирован. Это стандартный приём в SQL-инъекциях.

Как работает атака целиком?

Предположим, есть уязвимый запрос вида:

SELECT * FROM users WHERE id = '$input'

Если подставить нашу строку, получится:

SELECT * FROM users WHERE id = ')))) AND EXTRACTVALUE(7821,CONCAT(0x7e,((SELECT (ELT(7821=7821,1)))),0x7e))-- -'

После подстановки MySQL выполнит:

  1. Закроет кавычку и скобки (если они были).
  2. Проверит условие AND.
  3. Вызовет EXTRACTVALUE с некорректным XPath, содержащим ~1~.
  4. Сгенерирует ошибку вида: XPATH syntax error: '~1~'.
  5. Если приложение выводит ошибки БД на экран, атакующий увидит ~1~ и поймёт, что инъекция успешна.

Далее вместо ELT(7821=7821,1) можно подставить подзапрос, возвращающий нужные данные, например (SELECT password FROM users LIMIT 1), и получить их в тексте ошибки.

Почему это опасно?

Error-based SQL-инъекции позволяют злоумышленнику извлекать произвольные данные из базы: логины, пароли, номера карт, персональную информацию. В некоторых случаях через них можно выполнять административные операции или получить доступ к файловой системе сервера.

Как защититься?

  • Используйте подготовленные выражения (prepared statements). Это самый надёжный способ: параметры запроса передаются отдельно от SQL-кода и не интерпретируются как часть запроса.
  • Экранируйте пользовательский ввод. Если подготовленные выражения недоступны, применяйте функции экранирования, соответствующие вашей СУБД.
  • Отключите вывод ошибок БД в продакшене. Ошибки должны логироваться, но не показываться пользователю.
  • Ограничьте права пользователя БД. Приложение должно работать под учётной записью с минимально необходимыми привилегиями.
  • Используйте WAF. Веб-application firewall может блокировать известные шаблоны атак, но не заменяет исправление уязвимостей.
  • Регулярно проводите аудит кода и сканирование уязвимостей.

Заключение

Строка )))) AND EXTRACTVALUE(7821,CONCAT(0x7e,((SELECT (ELT(7821=7821,1)))),0x7e))-- - — это не случайный набор символов, а тщательно сконструированный эксплойт для проверки и эксплуатации error-based SQL-инъекций в MySQL. Понимание таких конструкций помогает разработчикам и специалистам по безопасности лучше защищать свои приложения.

Источники