> For the complete documentation index, see [llms.txt](https://an4ss-organization.gitbook.io/anas-almizani-blogs/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://an4ss-organization.gitbook.io/anas-almizani-blogs/research/cve-2025-4611.md).

# CVE-2025-4611 PoC

Mitre Description:

The Slim SEO – Fast & Automated WordPress SEO Plugin plugin for WordPress is vulnerable to Stored Cross-Site Scripting via the plugin's slim\_seo\_breadcrumbs shortcode in all versions up to, and including, 4.5.3 due to insufficient input sanitization and output escaping on user supplied attributes. 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.

#### CVE publish date: 21 may 2025

<https://nvd.nist.gov/vuln/detail/CVE-2025-4611>

### analysis: i have installed the right version through wordpress<br>

### we want to install the vulnarable version 4.5.3 and fixed version 4.5.4 for diffrent comparison

{% embed url="<https://downloads.wordpress.org/plugin/slim-seo.4.5.3.zip>" %}
Vulnarable version
{% endembed %}

{% embed url="<https://downloads.wordpress.org/plugin/slim-seo.4.5.4.zip>" %}
fixed version
{% endembed %}

### the vulnarable file in /slim-seo/src/Breadcrumbs.php

we will compare the 2 file in diffrent versions

<figure><img src="/files/2UP8WXa90c5Q4xl4es6g" alt=""><figcaption><p>line 109 &#x26; 110</p></figcaption></figure>

***

### **Vulnerable Function**

The vulnerable function is:

```php
public function render_shortcode( $atts ): string {
    $this->args = wp_parse_args( $atts, $this->args );
    $this->parse(); // builds $this->current and $this->links

    if ( 'true' === $this->args['display_current'] ) {
        $items[] = sprintf(
            '<span class="breadcrumb breadcrumb--last" aria-current="page">%s</span>',
            $this->current // Vulnerable value
        );
    }

    ...
}
```

The value of `$this->current` is output directly into HTML without escaping. If an attacker can influence this value, they can inject JavaScript or HTML into the page.

***

### **Call Chain: How It Gets Triggered**

#### 1. `render_shortcode()` is registered as a shortcode handler

```php
add_shortcode( 'slim_seo_breadcrumbs', [ $this, 'render_shortcode' ] );
```

This means it will execute when a page or post includes:

```wordpress
[slim_seo_breadcrumbs]
```

***

#### 2. `render_shortcode()` calls `parse()`

Within `render_shortcode()`, the method `parse()` is called:

```php
$this->parse();
```

This method sets `$this->current` depending on the context  post page

***

### **How the XSS Works**

#### Case: Search Page Context

Inside the `parse()` function:

```php
elseif ( is_search() ) {
    $this->current = sprintf( $this->args['label_search'], get_search_query() );
}
```

The default `label_search` is:

```php
'label_search' => __( 'Search Results for &#8220;%s&#8221;', 'slim-seo' ),
```

So the final output becomes:

```php
$this->current = 'Search Results for “' . get_search_query() . '”';
```

If the attacker controls `get_search_query()`, they can inject payloads.

***

#### No Output Encoding

The HTML is rendered as:

```php
<span class="breadcrumb breadcrumb--last" aria-current="page">
  {raw $this->current}
</span>
```

### in older version there’s no `esc_html()`, `htmlspecialchars()`, or `wp_kses()`. This leads directly to XSS.

***

### Steps:

1. WordPress detects this as a search query (`is_search()` returns true).
2. `get_search_query()` returns the attacker’s input.
3. `$this->current` becomes `“<script>alert(1)</script>”`.
4. It gets rendered directly into the page.
5. JavaScript executes in the victim’s browser.

## PoC:

on pages tab add a new page

<figure><img src="/files/ZuSinIGE2xBdBWRoBoDy" alt=""><figcaption></figcaption></figure>

after that go to + and search in patterns for breadcrumb

<figure><img src="/files/dppIvTOeKJdlzpOYIncR" alt=""><figcaption></figcaption></figure>

add the breadcrumb and go to settings for breadcrumb and change the label home to&#x20;

```
<img src=x onerror=alert(1)>
```

<figure><img src="/files/X5T8wxm0ER2g02YDsiNR" alt=""><figcaption></figcaption></figure>

### save the page and view the XSS :)

<figure><img src="/files/14m6TdsCNkYaRQ2IN8Cp" alt=""><figcaption></figcaption></figure>
