Lucene search
K

Microsoft SQL Server Interesting Data Finder

🗓️ 07 Jul 2010 14:48:08Reported by Robin Wood <[email protected]>Type 
metasploit
 metasploit
🔗 www.rapid7.com👁 31 Views

Microsoft SQL Server Interesting Data Finder module will search MSSQL server for 'interesting' columns and data. Tested against SQL Server 2019 Docker image

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

##
# Author: Robin Wood <[email protected]> <http://www.digininja.org>
# Version: 0.1
#
# This module will search the specified MSSQL server for
# 'interesting' columns and data
#
##

class MetasploitModule < Msf::Auxiliary
  include Msf::Exploit::Remote::MSSQL
  include Msf::OptionalSession::MSSQL

  def initialize(info = {})
    super(update_info(info,
      'Name'           => 'Microsoft SQL Server Interesting Data Finder',
      'Description'    => %q{
        This module will search the specified MSSQL server for
        'interesting' columns and data.

        This module has been tested against the latest SQL Server 2019 docker container image (22/04/2021).
      },
      'Author'         => [ 'Robin Wood <robin[at]digininja.org>' ],
      'License'        => MSF_LICENSE,
      'References'     =>
        [
          [ 'URL', 'http://www.digininja.org/metasploit/mssql_idf.php' ],
        ]
    ))

    register_options(
      [
        OptString.new('NAMES', [ true, 'Pipe separated list of column names',  'passw|bank|credit|card']),
      ])
  end

  def print_with_underline(str)
    print_line(str)
    print_line("=" * str.length)
  end

  def run
    headings = [
      ["Database", "Schema", "Table", "Column", "Data Type", "Row Count"]
    ]

    sql = ""
    sql += "DECLARE @dbname nvarchar(255), @id int, @sql varchar (4000); "
    sql += "DECLARE table_cursor CURSOR FOR SELECT name FROM sys.databases "
    sql += "OPEN table_cursor "
    sql += "FETCH NEXT FROM table_cursor INTO @dbname "
    sql += "WHILE (@@FETCH_STATUS = 0) "
    sql += "BEGIN "
    sql += "SET @sql = 'select ';"
    sql += "SET @sql = @sql + ' ''' + @dbname + ''' as ''Database'', ';"
    sql += "SET @sql = @sql + 'sys.schemas.name as ''Schema'', ';"
    sql += "SET @sql = @sql + 'sys.objects.name as ''Table'', ';"
    sql += "SET @sql = @sql + 'sys.columns.name as ''Column'', ';"
    sql += "SET @sql = @sql + 'sys.types.name as ''Column Type'' ';"
    sql += "SET @sql = @sql + 'from ' + @dbname + '.sys.columns ';"
    sql += "SET @sql = @sql + 'inner join ' + @dbname + '.sys.objects on sys.objects.object_id = sys.columns.object_id ';"
    sql += "SET @sql = @sql + 'inner join ' + @dbname + '.sys.types on sys.types.user_type_id = sys.columns.user_type_id ';"
    sql += "SET @sql = @sql + 'inner join ' + @dbname + '.sys.schemas on sys.schemas.schema_id = sys.objects.schema_id ';"

    list = datastore['Names']
    where = "SET @sql = @sql + ' WHERE ("
    list.split(/\|/).each { |val|
      where += " lower(sys.columns.name) like ''%" + val + "%'' OR "
    }

    where.slice!(-3, 4)

    where += ") ';"

    sql += where

    sql += "SET @sql = @sql + 'and sys.objects.type=''U'';';"
    sql += "EXEC (@sql);"
    sql += "FETCH NEXT FROM table_cursor INTO @dbname "
    sql += "END "
    sql += "CLOSE table_cursor "
    sql += "DEALLOCATE table_cursor "

    begin
      if session
        set_mssql_session(session.client)
      else
        unless mssql_login_datastore
          print_error('Login failed')
          return
        end
      end
      result = mssql_query(sql, false)
    rescue Rex::ConnectionRefused => e
      print_error("Connection failed: #{e}")
      return
    end

    column_data = result[:rows]
    widths = [0, 0, 0, 0, 0, 9]
    total_width = 0

    if result[:errors] && !result[:errors].empty?
      result[:errors].each do |err|
        print_error(err)
      end
    end

    if column_data.nil?
      print_error("No columns matched the pattern #{datastore['NAMES'].inspect}. Set the NAMES option to change this search pattern.")
      return
    end

    (column_data|headings).each { |row|
      0.upto(4) { |col|
        widths[col] = row[col].length if row[col].length > widths[col]
      }
    }

    widths.each { |a|
      total_width += a
    }

    print_line

    buffer = ""
    headings.each { |row|
      0.upto(5) { |col|
        buffer += row[col].ljust(widths[col] + 1)
      }
      print_line(buffer)
      print_line
      buffer = ""

      0.upto(5) { |col|
        buffer += print "=" * widths[col] + " "
      }
      print_line(buffer)
      print_line
    }

    column_data.each { |row|
      count_sql = "SELECT COUNT(*) AS count FROM "

      full_table = ""
      column_name = ""
      buffer = ""
      0.upto(4) { |col|
        full_table += row[col] + '.' if col < 3
        column_name = row[col] if col == 3
        buffer += row[col].ljust(widths[col] + 1)
      }
      full_table.slice!(-1, 1)
      count_sql += full_table

      result = mssql_query(count_sql, false) if mssql_login_datastore

      count_data = result[:rows]
      row_count = count_data[0][0]

      buffer += row_count.to_s
      print_line(buffer)
      print_line
    }

    print_line
    disconnect
  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