Skip to content
KitploitKITPLOIT
ToolsExploitsBlog
Log in
Submit
ToolsExploitsBlog
Submit

Hacking, PenTest, and Cybersecurity Tools for Your Security Arsenal!

Kitploit is a directory of hacking, cybersecurity, and pentesting tools. Discover the latest project updates to find vulnerabilities, analyze systems, automate testing, and strengthen your security.

··Feeds·Contact·Privacy·© 2026 Kitploit

Tool Directory

Categories

View all categories
Loading categories
CVE-2025-11262-Lab — Docker lab for reproducing CVE-2025-11262, an unauthenticated stored blind XSS in Link Whisper Free WordPress plugin. Includes vulnerable and patched targets, PoC script, and root cause analysis. | Kitploit
Tools/GitHubGitHub/rootdirective-sec/cve-2025-11262-lab
Vulnerability AnalysisWeb Application ExploitationCTFPenetration TestingLearning & EducationLabs & Practice
GitHubrootdirective-sec/cve-2025-11262-lab

CVE-2025-11262-Lab

Docker lab for reproducing CVE-2025-11262, an unauthenticated stored blind XSS in Link Whisper Free WordPress plugin. Includes vulnerable and patched targets, PoC script, and root cause analysis.

View Repository
623 months agoNot yet reviewed

Most Popular

View all →

Discover the most used tools by our community.

Explore all tools

Browse our collection of tools

View all tools →
Share

CVE-2025-11262 - Link Whisper Free Unauthenticated Stored Blind XSS

Executive Summary

This repository contains a local Docker lab for reproducing CVE-2025-11262, an unauthenticated stored cross-site scripting issue affecting the WordPress plugin Link Whisper Free.

The lab compares two plugin versions:

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

The demonstrated vulnerability chain is:

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

The attacker does not need to be logged in to plant the stored payload. The JavaScript executes later when a privileged WordPress user opens the affected admin page.

This lab is designed for controlled local research, source-level understanding, and portfolio demonstration only.

Verified Facts

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.

นี่คือส่วน Root Cause Summary สำหรับเอาไปแทนใน README ได้เลยครับ เป็น public-safe ไม่พูดถึงไฟล์ภายในอย่าง vuln_detail.txt และอิงกับ lab/source ที่คุณใช้ตอนนี้

Root Cause Summary

CVE-2025-11262 is caused by a stored JavaScript injection chain in Link Whisper Free 0.9.0.

The issue is not a single missing escaping call. It is a chain of multiple unsafe behaviors:

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

Unauthenticated REST endpoint

Link Whisper Free registers an AI authentication REST endpoint under the plugin REST namespace:

const REST_SLUG = 'link-whisper';
const AI_AUTH = 'ai-auth';

The endpoint is registered as a POST route:

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

Because the permission callback is __return_true, the endpoint is reachable without authentication.

In the lab, the effective endpoint is:

/wp-json/link-whisper/ai-auth

This means an unauthenticated attacker can send a request to the endpoint without a WordPress session, nonce, or administrator account.

Vulnerable input handling in 0.9.0

In Link Whisper Free 0.9.0, the handler reads attacker-controlled parameters from the REST request:

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 ]);
}

The vulnerable behavior is the weak validation condition:

if(!empty($token) && false !== strpos($token, 'ai-')){

This only checks whether the supplied access token contains the string ai-.

There is no strict validation of user_id before it is stored:

update_option('wpil_ai_access_user_id', $user_id);

As a result, attacker-controlled JavaScript can be persisted in the WordPress options table.

Persistent storage

The attacker-controlled user_id value is stored in the WordPress option:

wpil_ai_access_user_id

In this lab, the PoC sends the following local-only payload:

</script><script>alert("CVE-2025-11262-LAB")</script>

On the vulnerable service, the payload is stored as the value of wpil_ai_access_user_id.

The attacker does not need to be logged in to plant the payload. The payload is planted through the unauthenticated REST endpoint.

Admin JavaScript sink

The stored value is later retrieved through the plugin settings logic:

public static function get_linkwhisper_ai_user_id(){
    return get_option('wpil_ai_access_user_id', '');
}

The value is assigned to $ai_id and rendered into the AI Subscription admin page.

In Link Whisper Free 0.9.0, the value is inserted directly into a JavaScript string:

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

Because $ai_id is not escaped before being inserted into the JavaScript context, a stored payload can break out of the intended string and execute JavaScript when the admin page is opened.

With the lab payload, the vulnerable rendered output becomes equivalent to:

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

In a browser, the injected closing </script> tag terminates the original script block, and the injected <script> block executes.

Trigger condition

The payload is planted by an unauthenticated attacker, but execution requires a privileged WordPress user to open the affected admin page:

/wp-admin/admin.php?page=link_whisper_ai_subscription

In this lab, the affected page is opened as the WordPress administrator to trigger the alert dialog.

This makes the issue an unauthenticated stored XSS targeting authenticated WordPress administrators or privileged users who can access the Link Whisper AI Subscription admin page.

Patch behavior in 0.9.1

Link Whisper Free 0.9.1 adds stricter validation before storing the AI authentication values.

The patched handler requires the token and user ID to match strict formats:

Download Tool