WP Plugin Info Card <= 6.2.0 - Cross-Site Request Forgery to Arbitrary Custom Plugin Entry Creation
Description
The WP Plugin Info Card plugin for WordPress is vulnerable to Cross-Site Request Forgery in all versions up to, and including, 6.2.0. This is due to missing nonce validation in the ajax_save_custom_plugin() function, which is disabled by prefixing the check with 'false &&'. This makes it possible for unauthenticated attackers to create or modify custom plugin entries via a forged request granted they can trick a site administrator into performing an action such as clicking on a link.
CVSS Vector Breakdown
CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:N/I:L/A:NTechnical Details
<=6.2.0What Changed in the Fix
Changes introduced in v6.3.0
Source Code
WordPress.org SVNThis research plan outlines the steps to demonstrate a Cross-Site Request Forgery (CSRF) vulnerability in the **WP Plugin Info Card** plugin, which allows an attacker to create or modify custom plugin entries by tricking an administrator into submitting a forged request. ### 1. Vulnerability Summar…
Show full research plan
This research plan outlines the steps to demonstrate a Cross-Site Request Forgery (CSRF) vulnerability in the WP Plugin Info Card plugin, which allows an attacker to create or modify custom plugin entries by tricking an administrator into submitting a forged request.
1. Vulnerability Summary
- Vulnerability: Cross-Site Request Forgery (CSRF) to Arbitrary Custom Plugin Entry Creation.
- Affected Function:
MediaRon\WPPIC\Admin\Init::ajax_save_custom_plugin(). - File:
php/Admin/Init.php. - Nature of Flaw: The plugin fails to validate WordPress nonces in the
ajax_save_custom_plugin()function. According to the vulnerability description, the nonce check was intentionally or accidentally disabled by prefixing the condition withfalse &&, causing the verification to always be skipped. - Impact: An unauthenticated attacker can create new "Custom Plugin" entries (likely stored as a Custom Post Type) or modify existing ones if they can trick a logged-in administrator into clicking a link or visiting a malicious site.
2. Attack Vector Analysis
- Endpoint:
/wp-admin/admin-ajax.php. - Action:
wppic_save_custom_plugin. - Method:
POST. - Authentication: Required (Administrator). The attack relies on the administrator's active session.
- Payload Parameters (Inferred from plugin purpose and JS structure):
action:wppic_save_custom_pluginid: (Optional) The ID of the post to modify. Omit or set to0for new entries.title: The name of the custom plugin.slug: The slug for the plugin.version: Plugin version string.author: Author name.description: Plugin description.nonce: (Optional/Any value) Due to thefalse &&bypass, the server ignores the validity of this token.
3. Code Flow
- Entry Point: The AJAX action is registered in
php/Admin/Init.php's constructor:add_action( 'wp_ajax_wppic_save_custom_plugin', array( $this, 'ajax_save_custom_plugin' ) ); - Execution: When a
POSTrequest is sent toadmin-ajax.phpwithaction=wppic_save_custom_plugin, WordPress invokes theajax_save_custom_plugin()method. - Vulnerable Sink: Inside
ajax_save_custom_plugin(), the code attempts a nonce check:if ( false && ! wp_verify_nonce( ... ) ) { ... } - Bypass: Because
false && anythingis alwaysfalse, the error block is never entered. - Persistence: The function proceeds to process the
$_POSTdata and useswp_insert_post()orupdate_post_meta()to store the custom plugin entry in the database.
4. Nonce Acquisition Strategy (Optional)
While the vulnerability description states the nonce check is bypassed, a robust exploit should identify where the nonce would have been located if it were enforced.
- Shortcode/Page: The Custom Plugin management interface is located in the WordPress Admin dashboard under WP Plugin Info Card > Custom Plugins.
- JS Localization: The script
dist/wppic-admin-custom-plugin.jsis enqueued for this page. - Extraction:
- Navigate to
/wp-admin/admin.php?page=wppic-custom-plugins(inferred slug). - Use
browser_evalto find localized data. The plugin likely uses a global JS object to store settings. - Check
window.wppic_admin_custom_pluginor similar. - Note: In this specific CVE, the
noncevalue can be any string (e.g.,1234567890) because the server-side check is disabled.
- Navigate to
5. Exploitation Strategy
The goal is to create a new Custom Plugin entry via an auto-submitting HTML form (simulating a CSRF attack).
Step-by-Step:
- Identify the base URL of the WordPress instance.
- Construct a POST request to
admin-ajax.php. - Include parameters that define a new plugin entry.
Example Request (using http_request):
{
"method": "POST",
"url": "http://localhost:8888/wp-admin/admin-ajax.php",
"headers": {
"Content-Type": "application/x-www-form-urlencoded"
},
"body": "action=wppic_save_custom_plugin&title=CSRF_Exploit_Plugin&slug=csrf-plugin&version=1.3.37&author=Attacker&description=This+was+created+via+CSRF&nonce=deadbeef"
}
6. Test Data Setup
- Plugin Activation: Ensure
wp-plugin-info-cardversion 6.2.0 is installed and active. - Admin Access: Ensure an administrator user exists (to provide the session context for the CSRF).
- Identify Post Type: Custom plugins are likely stored as a post type named
wppic-custom-plugin(or similar). Runwp post-type listto confirm.
7. Expected Results
- The server should respond with a JSON success message:
{"success":true,"data":{...}}. - A new post of the custom plugin type should be created in the
wp_poststable. - The post meta should contain the
slug,version, andauthorprovided in the payload.
8. Verification Steps
After executing the http_request, verify the creation of the plugin entry via WP-CLI:
- List Custom Plugins:
wp post list --post_type=wppic-custom-plugin --format=ids - Check Metadata:
Replace<ID>with the ID found in the previous step:wp post get <ID> --field=post_titlewp post get <ID> --field=post_contentwp post-meta list <ID> - Confirm Lack of Nonce Check:
Retry the exploit with an emptynonceparameter. If it still succeeds, thefalse &&bypass is confirmed.
9. Alternative Approaches
If the simple POST fails:
- JSON Payload: Check if the AJAX handler expects
application/jsoninstead of form-urlencoded. This is common in React-based admin panels (as indicated by thereactdependency inwppic-admin-custom-plugin.asset.php). - Modification: Attempt to modify an existing entry by providing an
idparameter. First, manually create a custom plugin to get its ID, then attempt to change itstitlevia CSRF.
Summary
The WP Plugin Info Card plugin for WordPress is vulnerable to Cross-Site Request Forgery (CSRF) in versions up to 6.2.0. This is caused by a disabled nonce check in the `ajax_save_custom_plugin()` function, where the verification logic is prefixed with 'false &&', allowing attackers to create or modify custom plugin entries by tricking an administrator into performing an action.
Vulnerable Code
// php/Admin/Init.php public function ajax_save_custom_plugin() { if ( ! current_user_can( 'manage_options' ) ) { return; } $nonce = sanitize_text_field( filter_input( INPUT_POST, 'nonce', FILTER_DEFAULT ) ); if ( false && ! wp_verify_nonce( $nonce, 'wppic-admin-custom-plugin-save' ) ) { wp_send_json_error( array( 'message' => __( 'Nonce verification failed', 'wp-plugin-info-card' ), 'type' => 'error', 'dismissable' => true, ) ); }
Security Fix
@@ -342,7 +342,7 @@ } $nonce = sanitize_text_field( filter_input( INPUT_POST, 'nonce', FILTER_DEFAULT ) ); - if ( false && ! wp_verify_nonce( $nonce, 'wppic-admin-custom-plugin-save' ) ) { + if ( ! wp_verify_nonce( $nonce, 'wppic-admin-custom-plugin-save' ) ) { wp_send_json_error( array( 'message' => __( 'Nonce verification failed', 'wp-plugin-info-card' ),
Exploit Outline
The exploit targets the AJAX endpoint `admin-ajax.php` using the `wppic_save_custom_plugin` action. Because the server-side nonce verification is effectively disabled with a `false &&` condition, an attacker only needs to trick a logged-in administrator into visiting a malicious page that auto-submits a POST request. The payload includes parameters like `title`, `slug`, `version`, `author`, and `description` to create a new custom plugin entry or an `id` to modify an existing one. Since the nonce check always evaluates to false, any value (or no value) for the `nonce` parameter is accepted.
Check if your site is affected.
Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.