
Статический аудит кода CVE-2024-57521 — аутентифицированной SQL-инъекции в модуле генератора RuoYi-Vue, с анализом от источника к стоку и PoC обхода фильтра через %0b.
Данный репозиторий предназначен исключительно для целей безопасности и образования. Не используйте описанные в этом документе методы для несанкционированных атак. Все тесты проводились в локальной среде статического аудита кода.
ruoyi-generator)ruoyi-generator/src/main/java/com/ruoyi/generator/controller/GenController.javaКлючевой код:
@PostMapping("/createTable")
public AjaxResult createTableSave(@RequestParam("sql") String sql, @RequestParam("tplWebType") String tplWebType)
{
try
{
SqlUtil.filterKeyword(sql); // вызов фильтра перед входом в бизнес-логику
Анализ: администратор панели управления может передать произвольный SQL-запрос на создание таблицы через параметр sql HTTP POST-запроса. Точка входа не обеспечивает достаточного ограничения пользовательского ввода и напрямую передаёт его последующему фильтру.
Скриншот-подтверждение:

· Расположение файла: ruoyi-common/src/main/java/com/ruoyi/common/utils/sql/SqlUtil.java
Код с ключевым дефектом:
// строка 16: определение чёрного списка, обратите внимание на 【завершающий пробел】 в ключевых словах
public static String SQL_REGEX = "\u0008|%0A|and |extractvalue|updatexml|sleep|information_schema|exec...";
// строки 61-66: логика фильтрации
String normalizedValue = value.replaceAll("\\p{Z}|\\s", ""); // сначала удаляются все пробелы из ввода
String[] sqlKeywords = StringUtils.split(SQL_REGEX, "\\|");
for (String sqlKeyword : sqlKeywords)
{
if (StringUtils.indexOfIgnoreCase(normalizedValue, sqlKeyword) > -1)
{
throw new UtilException("请求参数包含敏感关键词" + sqlKeyword + ",可能存在安全风险");
}
}
Анализ дефекта: фильтр сначала выполняет replaceAll("\p{Z}|\s", ""), удаляя все пробельные символы из ввода. Однако ключевые слова в чёрном списке SQL_REGEX (такие как "and ", "select ") содержат завершающий пробел. Это приводит к тому, что сопоставление неизбежно терпит неудачу: достаточно заменить пробел после ключевого слова на %0b (вертикальная табуляция), чтобы идеально обойти проверку чёрного списка.
Скриншоты-подтверждения:
· Расположение файла: ruoyi-generator/src/main/resources/mapper/generator/GenTableMapper.xml
Ключевой код:
<update id="createTable">
${sql}
</update>
Анализ: в MyBatis конструкция ${} выполняет прямую конкатенацию строк вместо безопасной предварительной компиляции #{} . В результате вредоносный SQL, обошедший фильтр, передаётся в базу данных на выполнение. Это типичная комбинированная уязвимость «фильтрация по чёрному списку + небезопасная конкатенация».
Скриншот-подтверждение:
· Способ: атакующий использует %0b (вертикальная табуляция MySQL, входящая в диапазон совпадения \s) вместо пробелов в SQL-запросе.
· Принцип обнаружения: использование IF(<условие>, 1, 1/0) в качестве детектора булевой слепой инъекции. · Условие ложно: срабатывает ошибка деления на ноль, сервер возвращает HTTP 500. · Условие истинно: нормальный ответ без ошибок. · Метод извлечения: с помощью метода деления пополам можно побитово угадывать данные базы данных.
Данная уязвимость является типичным обходом, вызванным «неполным исправлением». Разработчики при исправлении предыдущей аналогичной SQL-инъекции внедрили механизм чёрного списка, но упустили из виду, что чёрный список зависит от пробелов, а предшествующая логика удаления пробелов нарушает условия сопоставления чёрного списка, что в конечном итоге приводит к новому обходу (CVE-2024-57521).
· Отказаться от механизма чёрного списка: не полагайтесь на чёрные списки, безопасность основывается на белых списках. · Использовать предварительную компиляцию: замените ${sql} в MyBatis на предварительно компилируемый #{} . Если необходимо динамически передавать SQL (например, создание таблиц, Order By), следует использовать строгий разбор абстрактного синтаксического дерева (AST) или строгую валидацию параметров. · Усовершенствовать фильтр: если использование чёрного списка необходимо, следует удалить завершающие пробелы из ключевых слов чёрного списка и выполнять унифицированную нормализацию перед сравнением (например, приведение к нижнему регистру, замена %0b и подобных на пробелы).
· NVD - CVE-2024-57521 · Репозиторий RuoYi-Vue на Gitee