Что это за строка?
Строка ) AND EXTRACTVALUE(2177,CONCAT(0x7e,((SELECT (ELT(2177=2177,1)))),0x7e))-- - представляет собой классический пример error-based SQL-инъекции для СУБД MySQL. Она предназначена для внедрения в уязвимый SQL-запрос с целью заставить сервер базы данных выдать сообщение об ошибке, содержащее полезные данные (например, версию СУБД, имя базы, логины и пароли пользователей).
Подобные строки часто встречаются в логах веб-серверов, в полях ввода форм, в параметрах URL. Для неподготовленного человека они выглядят как случайный набор символов, но на самом деле это тщательно сконструированная атака.
Разбор по частям
Давайте разберём каждый элемент этого запроса.
- ) — закрывающая скобка. Она нужна, чтобы «закрыть» ранее открытую скобку в оригинальном SQL-запросе, куда внедряется инъекция. Например, если исходный запрос был
SELECT * FROM users WHERE id = (1), то злоумышленник подставляет1) AND ..., чтобы синтаксис остался корректным. - AND — логический оператор, который соединяет внедряемое условие с оригинальным. Это позволяет не нарушить логику запроса, но добавить выполнение вредоносной функции.
- EXTRACTVALUE(2177, ...) — функция MySQL для работы с XML. Она извлекает значение из XML-строки. Первый аргумент — XML-документ (в нашем случае просто число 2177, которое не является валидным XML), второй — XPath-выражение. Если XPath содержит недопустимые символы, MySQL генерирует ошибку, в тексте которой выводится переданное значение.
- CONCAT(0x7e, ..., 0x7e) — функция конкатенации строк.
0x7e— это шестнадцатеричный код символа~(тильда). Тильды используются как маркеры, чтобы в сообщении об ошибке было легко найти внедрённые данные. - (SELECT (ELT(2177=2177,1))) — подзапрос, который возвращает результат.
ELT()— функция MySQL, возвращающая N-й элемент из списка. Здесь2177=2177— это всегда истинное условие (1), поэтомуELT(1,1)вернёт1. В реальной атаке вместо этого подзапроса мог бы быть, например,(SELECT password FROM users LIMIT 1). - -- - — комментарий. В MySQL
--начинает комментарий до конца строки, но требует пробела после себя. Дефис в конце (-- -) часто используется, чтобы гарантировать, что комментарий точно начался, даже если пробел будет утерян при передаче.
Как это работает
Предположим, уязвимый запрос выглядит так:
SELECT * FROM articles WHERE id = (1)
Злоумышленник передаёт в параметр id значение:
1) AND EXTRACTVALUE(2177,CONCAT(0x7e,((SELECT (ELT(2177=2177,1)))),0x7e))-- -
После подстановки запрос становится:
SELECT * FROM articles WHERE id = (1) AND EXTRACTVALUE(2177,CONCAT(0x7e,((SELECT (ELT(2177=2177,1)))),0x7e))-- -)
MySQL пытается выполнить EXTRACTVALUE с первым аргументом 2177. Поскольку это не XML, функция выдаёт ошибку. Второй аргумент — XPath-выражение, которое начинается с ~ (тильда), что недопустимо в XPath. MySQL формирует сообщение об ошибке вида:
XPATH syntax error: '~1~'
В этом сообщении мы видим ~1~ — это и есть результат выполнения подзапроса (SELECT (ELT(2177=2177,1))). Если бы вместо 1 подставлялся пароль пользователя, он бы отобразился в ошибке.
Зачем это нужно злоумышленнику
Error-based SQL-инъекции — один из самых простых способов извлечения данных из базы, когда приложение не выводит результаты запроса напрямую, но отображает сообщения об ошибках СУБД. Атакующий может:
- Получить версию MySQL (например,
SELECT version()). - Узнать имя текущей базы данных (
SELECT database()). - Извлечь имена таблиц и колонок из
information_schema. - Вытащить логины, пароли, хеши, номера кредитных карт и любые другие данные, хранящиеся в БД.
В приведённом примере 2177=2177 — это демонстрация работоспособности инъекции. Злоумышленник проверяет, что уязвимость существует и что функция EXTRACTVALUE доступна. Если ошибка с тильдами возвращается, значит, можно переходить к реальному извлечению данных.
Почему используется именно EXTRACTVALUE
В MySQL есть несколько функций, вызывающих ошибки с контролируемым текстом: EXTRACTVALUE, UPDATEXML, GTID_SUBSET и другие. EXTRACTVALUE долгое время была популярна, потому что:
- Она доступна во всех версиях MySQL 5.x и многих 8.x.
- Сообщение об ошибке содержит до 32 символов полезной нагрузки.
- Синтаксис прост:
EXTRACTVALUE(1, CONCAT(0x7e, (SELECT ...), 0x7e)).
Однако начиная с MySQL 8.0.17 функция EXTRACTVALUE была удалена, поэтому современные атаки чаще используют UPDATEXML или другие техники. Но старые системы по-прежнему уязвимы.
Как защититься
Главная защита от SQL-инъекций — использование параметризованных запросов (prepared statements). Это означает, что данные пользователя передаются в базу отдельно от SQL-кода и не могут изменить структуру запроса.
Дополнительные меры:
- Экранирование специальных символов с помощью функций вроде
mysqli_real_escape_string(устаревший подход). - Валидация и фильтрация входных данных (например, проверка, что
id— это число). - Отключение вывода ошибок СУБД в продакшене, чтобы атакующий не видел текст ошибок.
- Использование ORM и query builder'ов, которые автоматически параметризуют запросы.
- Регулярное обновление СУБД и фреймворков.
Если вы обнаружили такую строку в логах, это признак того, что ваш сайт пытались взломать. Следует проверить код на наличие уязвимостей и, при необходимости, обратиться к специалистам по безопасности.
Краткий итог
Строка ) AND EXTRACTVALUE(2177,CONCAT(0x7e,((SELECT (ELT(2177=2177,1)))),0x7e))-- - — это не случайный набор символов, а работающий эксплойт для error-based SQL-инъекции в MySQL. Он использует функцию EXTRACTVALUE для вызова ошибки, в тексте которой выводятся данные подзапроса. Понимание таких конструкций помогает разработчикам и администраторам лучше защищать свои системы.
Комментарии
—Войдите, чтобы оставить комментарий