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

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

Подобные строки часто встречаются в логах веб-серверов, в полях ввода форм, в URL-параметрах и заголовках. Если вы увидели её — значит, кто-то (или автоматический сканер) пытался проверить сайт на наличие SQL-инъекции. Понимание того, как она работает, помогает разработчикам и администраторам защищать свои системы.

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

Давайте разберём строку на составляющие, чтобы понять логику атаки.

  • Обратная кавычка (`) — используется для закрытия незакрытого идентификатора в исходном SQL-запросе. Если приложение подставляет пользовательский ввод в запрос без экранирования, обратная кавычка может «разорвать» строку и добавить произвольный код.
  • OR — логический оператор. Внедряется, чтобы изменить условие WHERE исходного запроса. Например, вместо WHERE id = '...' получается WHERE id = '' OR ..., что может сделать условие всегда истинным.
  • EXTRACTVALUE(1064, CONCAT(...)) — функция MySQL, предназначенная для работы с XML. Она принимает два аргумента: XML-документ и XPath-выражение. Если XPath-выражение некорректно, MySQL генерирует ошибку, в тексте которой отображается переданное значение. Злоумышленники используют это для вывода данных: первый аргумент (1064) — произвольное число, а второй — конкатенация с данными из БД.
  • CONCAT(0x7e, ((SELECT (ELT(1064=1064,1)))), 0x7e) — функция CONCAT объединяет строки. 0x7e — это шестнадцатеричное представление символа ~ (тильда). Тильда используется как маркер, чтобы легко найти выводимые данные в сообщении об ошибке. Внутри — подзапрос SELECT (ELT(1064=1064,1)).
  • ELT(1064=1064,1) — функция ELT возвращает N-й элемент из списка. Первый аргумент — условие 1064=1064, которое всегда истинно (равно 1). Второй аргумент — 1. Таким образом, ELT(1,1) вернёт 1. Это простейшая проверка, которая в реальной атаке заменяется на подзапрос, извлекающий данные (например, имя пользователя или пароль).
  • -- - — комментарий. В MySQL -- начинает комментарий до конца строки, но требуется пробел после двух дефисов. Символ - в конце часто добавляют для надёжности, чтобы комментарий точно сработал. Всё, что идёт после, игнорируется парсером SQL.

Как это работает на практике

Предположим, на сайте есть страница product.php?id=1, и в коде выполняется запрос:

SELECT * FROM products WHERE id = '$id'

Злоумышленник подставляет вместо $id нашу строку. Запрос превращается в:

SELECT * FROM products WHERE id = '` OR EXTRACTVALUE(1064,CONCAT(0x7e,((SELECT (ELT(1064=1064,1)))),0x7e))-- -'

СУБД выполняет запрос. Функция EXTRACTVALUE получает на вход число 1064 (не XML) и строку, начинающуюся с тильды. Поскольку 1064 не является корректным XML-документом, MySQL выбрасывает ошибку вида:

XPATH syntax error: '~1~'

В сообщении об ошибке отображается результат выполнения CONCAT — то, что злоумышленник поместил между тильдами. В данном примере это 1. В реальной атаке вместо ELT(1064=1064,1) подставляется подзапрос, например:

(SELECT password FROM users LIMIT 1)

Тогда в ошибке появится хеш пароля. Так посимвольно или целыми строками можно извлечь любые данные из базы.

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

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

SQL-инъекции остаются в списке OWASP Top 10 на протяжении многих лет. По данным OWASP, это одна из самых распространённых и разрушительных уязвимостей веб-приложений. Причина — недостаточная проверка пользовательского ввода и конкатенация строк при построении SQL-запросов.

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

Основной способ защиты — использовать параметризованные запросы (prepared statements). В этом случае пользовательский ввод передаётся отдельно от SQL-кода и не может изменить структуру запроса. Например, в PHP с PDO:

$stmt = $pdo->prepare('SELECT * FROM products WHERE id = :id');
$stmt->execute(['id' => $_GET['id']]);

Дополнительные меры:

  • Валидация и фильтрация входных данных (например, приведение id к целому числу).
  • Экранирование специальных символов с помощью функций вроде mysqli_real_escape_string (но это менее надёжно, чем prepared statements).
  • Использование ORM, которые автоматически параметризуют запросы.
  • Отключение вывода подробных ошибок БД в production-окружении, чтобы злоумышленник не видел текст ошибки.
  • Регулярное сканирование кода и пентесты.

Что делать, если вы увидели такую строку в логах?

Если строка появилась в логах вашего сайта, это признак того, что сайт сканируют на уязвимости. Не паникуйте, но проверьте:

  1. Есть ли на сайте формы или параметры, которые передаются в SQL-запросы без параметризации.
  2. Используются ли prepared statements во всех местах работы с БД.
  3. Настроен ли вывод ошибок так, чтобы они не показывались пользователю.
  4. Ведётся ли мониторинг подозрительной активности.

Если вы не разработчик, сообщите об инциденте администратору сайта или в службу безопасности. Игнорировать такие сигналы нельзя: за сканированием может последовать реальная атака.

Заключение

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

Источники