Что означает строка OR EXTRACTVALUE(1100,CONCAT(0x7e,((SELECT (ELT(1100=1100,1)))),0x7e))-- -?
Эта строка — классический пример error-based SQL-инъекции (инъекции на основе ошибок) для СУБД MySQL. Она предназначена для извлечения данных из базы через вывод сообщения об ошибке. Подобные конструкции часто встречаются в отчётах об уязвимостях и в логах веб-серверов, когда злоумышленник пытается проэксплуатировать недостаточную фильтрацию пользовательского ввода.
Внешне выражение выглядит как часть SQL-запроса, которая добавляется к легитимному запросу через оператор OR. Если приложение не экранирует специальные символы, база данных выполнит внедрённый код и вернёт результат в виде ошибки, которую атакующий может прочитать.
Разбор по частям
1. OR
Логический оператор OR используется для присоединения вредоносного условия к исходному запросу. Например, если исходный запрос был SELECT * FROM users WHERE id = 1, то после подстановки получится SELECT * FROM users WHERE id = 1 OR EXTRACTVALUE(...). Поскольку OR возвращает истину, если хотя бы одно из условий истинно, внедрённая функция будет выполнена.
2. EXTRACTVALUE(1100, CONCAT(0x7e, ((SELECT (ELT(1100=1100,1)))), 0x7e))
EXTRACTVALUE() — это встроенная функция MySQL, предназначенная для извлечения значения из XML-строки. Она принимает два аргумента: XML-документ и XPath-выражение. Если XPath-выражение некорректно, функция генерирует ошибку, в тексте которой может содержаться переданное значение. Этим и пользуются злоумышленники.
В нашем случае первым аргументом идёт число 1100 — это не XML, но MySQL попытается его интерпретировать. Второй аргумент — CONCAT(0x7e, ((SELECT (ELT(1100=1100,1)))), 0x7e) — конструирует строку, которая будет вставлена в сообщение об ошибке.
3. CONCAT(0x7e, ..., 0x7e)
CONCAT() объединяет строки. 0x7e — это шестнадцатеричное представление символа ~ (тильда). Тильда используется как маркер, чтобы облегчить поиск вывода в тексте ошибки. Между двумя тильдами вставляется результат подзапроса.
4. (SELECT (ELT(1100=1100,1)))
ELT() — функция MySQL, которая возвращает N-й элемент из списка. Синтаксис: ELT(N, str1, str2, ...). В нашем случае ELT(1100=1100, 1): выражение 1100=1100 истинно, то есть равно 1 (в MySQL истина — это 1). Значит, ELT(1, 1) вернёт первый элемент списка — число 1. Подзапрос SELECT (ELT(...)) просто возвращает это значение.
Таким образом, вся конструкция CONCAT(0x7e, (SELECT (ELT(1100=1100,1))), 0x7e) создаст строку ~1~.
5. -- -
Два дефиса и пробел (или -- -) — это комментарий в SQL. Всё, что идёт после них, игнорируется базой данных. Это нужно, чтобы «отрезать» остаток оригинального запроса, который мог бы вызвать синтаксическую ошибку.
Как это работает целиком
Предположим, уязвимый запрос выглядит так:
SELECT * FROM articles WHERE id = $_GET['id']
Злоумышленник передаёт в параметр id значение:
1 OR EXTRACTVALUE(1100,CONCAT(0x7e,((SELECT (ELT(1100=1100,1)))),0x7e))-- -
После подстановки запрос становится:
SELECT * FROM articles WHERE id = 1 OR EXTRACTVALUE(1100,CONCAT(0x7e,((SELECT (ELT(1100=1100,1)))),0x7e))-- -
MySQL выполняет EXTRACTVALUE. Поскольку первый аргумент не является корректным XML, функция выдаёт ошибку. Но перед этим она вычисляет второй аргумент — строку ~1~. В тексте ошибки появится что-то вроде:
XPATH syntax error: '~1~'
Атакующий видит эту ошибку (если она выводится на страницу) и понимает, что инъекция работает. Далее он может заменить 1 в ELT на вызовы других функций, например, SELECT version() или SELECT password FROM users LIMIT 1, чтобы извлечь реальные данные.
Зачем это нужно злоумышленнику?
Error-based инъекции — один из самых быстрых способов получить информацию из базы, когда приложение выводит сообщения об ошибках. В отличие от blind-инъекций, где приходится задавать множество вопросов и анализировать время отклика, здесь данные возвращаются напрямую в тексте ошибки. Это делает атаку эффективной и малозаметной для систем, которые не логируют ошибки.
Как защититься?
- Используйте подготовленные выражения (prepared statements). Это самый надёжный способ: параметры запроса передаются отдельно от SQL-кода, и внедрение становится невозможным.
- Экранируйте специальные символы. Если по каким-то причинам нельзя использовать подготовленные выражения, применяйте функции экранирования, например
mysqli_real_escape_string(). - Отключите вывод ошибок на продакшене. Сообщения об ошибках не должны показываться пользователям — это лишает атакующего обратной связи.
- Ограничьте права пользователя БД. Не давайте веб-приложению прав на чтение системных таблиц или выполнение опасных функций.
- Используйте WAF. Веб-прикладной брандмауэр может блокировать подозрительные конструкции, такие как
EXTRACTVALUEв параметрах.
Вывод
Строка OR EXTRACTVALUE(1100,CONCAT(0x7e,((SELECT (ELT(1100=1100,1)))),0x7e))-- - — это не случайный набор символов, а тщательно сконструированный эксплойт для проверки уязвимости MySQL-инъекции. Понимание того, как он работает, помогает разработчикам и специалистам по безопасности лучше защищать свои приложения.
Комментарии
—Войдите, чтобы оставить комментарий