2012-01-10 23:32:09 +00:00
##
2014-10-17 16:47:33 +00:00
# This module requires Metasploit: http://metasploit.com/download
2013-10-15 18:50:46 +00:00
# Current source: https://github.com/rapid7/metasploit-framework
2012-01-10 23:32:09 +00:00
##
require 'yaml'
2016-03-08 13:02:44 +00:00
class MetasploitModule < Msf :: Auxiliary
2013-08-30 21:28:54 +00:00
include Msf :: Exploit :: Remote :: MSSQL
include Msf :: Auxiliary :: Report
include Msf :: Auxiliary :: Scanner
def initialize
super (
'Name' = > 'MSSQL Schema Dump' ,
'Description' = > %Q{
This module attempts to extract the schema from a MSSQL Server
Instance . It will disregard builtin and example DBs such
as master , model , msdb , and tempdb . The module will create
a note for each DB found , and store a YAML formatted output
as loot for easy reading .
} ,
'Author' = > [ 'theLightCosine' ] ,
'License' = > MSF_LICENSE
)
register_options ( [
OptBool . new ( 'DISPLAY_RESULTS' , [ true , " Display the Results to the Screen " , true ] )
] )
end
def run_host ( ip )
2016-03-06 05:11:39 +00:00
if ! mssql_login_datastore
2013-08-30 21:28:54 +00:00
print_error ( " #{ rhost } : #{ rport } - Invalid SQL Server credentials " )
return
end
2015-04-03 11:12:23 +00:00
# Grabs the Instance Name and Version of MSSQL(2k,2k5,2k8)
2013-08-30 21:28:54 +00:00
instancename = mssql_query ( mssql_enumerate_servername ( ) ) [ :rows ] [ 0 ] [ 0 ] . split ( '\\' ) [ 1 ]
print_status ( " Instance Name: #{ instancename . inspect } " )
version = mssql_query ( mssql_sql_info ( ) ) [ :rows ] [ 0 ] [ 0 ]
output = " Microsoft SQL Server Schema \n Host: #{ datastore [ 'RHOST' ] } \n Port: #{ datastore [ 'RPORT' ] } \n Instance: #{ instancename } \n Version: #{ version } \n ==================== \n \n "
2015-04-03 11:12:23 +00:00
# Grab all the DB schema and save it as notes
2013-08-30 21:28:54 +00:00
mssql_schema = get_mssql_schema
return nil if mssql_schema . nil? or mssql_schema . empty?
mssql_schema . each do | db |
report_note (
:host = > rhost ,
:type = > " mssql.db.schema " ,
:data = > db ,
:port = > rport ,
:proto = > 'tcp' ,
:update = > :unique_data
)
end
output << YAML . dump ( mssql_schema )
this_service = report_service (
:host = > datastore [ 'RHOST' ] ,
:port = > datastore [ 'RPORT' ] ,
:name = > 'mssql' ,
:proto = > 'tcp'
)
store_loot ( 'mssql_schema' , " text/plain " , datastore [ 'RHOST' ] , output , " #{ datastore [ 'RHOST' ] } _mssql_schema.txt " , " MS SQL Schema " , this_service )
print_good output if datastore [ 'DISPLAY_RESULTS' ]
end
def get_mssql_schema
mssql_db_names = get_db_names ( )
mssql_schema = [ ]
unless mssql_db_names . nil?
mssql_db_names . each do | dbname |
next if dbname [ 0 ] == 'model' or dbname [ 0 ] == 'master' or dbname [ 0 ] == 'msdb' or dbname [ 0 ] == 'tempdb'
tmp_db = { }
tmp_tblnames = get_tbl_names ( dbname [ 0 ] )
unless tmp_tblnames . nil?
tmp_db [ 'DBName' ] = dbname [ 0 ]
tmp_db [ 'Tables' ] = [ ]
tmp_tblnames . each do | tblname |
next if tblname [ 0 ] . nil?
tmp_tbl = { }
tmp_tbl [ 'TableName' ] = tblname [ 0 ]
tmp_tbl [ 'Columns' ] = [ ]
tmp_columns = get_columns ( dbname [ 0 ] , tblname [ 1 ] )
unless tmp_columns . nil?
tmp_columns . each do | column |
next if column [ 0 ] . nil?
tmp_column = { }
tmp_column [ 'ColumnName' ] = column [ 0 ]
tmp_column [ 'ColumnType' ] = column [ 1 ]
tmp_column [ 'ColumnLength' ] = column [ 2 ]
tmp_tbl [ 'Columns' ] << tmp_column
end
end
tmp_db [ 'Tables' ] << tmp_tbl
end
end
mssql_schema << tmp_db
end
end
return mssql_schema
end
2015-04-03 11:12:23 +00:00
# Gets all of the Databases on this Instance
2013-08-30 21:28:54 +00:00
def get_db_names
results = mssql_query ( mssql_db_names ( ) ) [ :rows ]
return results
end
2015-04-03 11:12:23 +00:00
# Gets all the table names for the given DB
2013-08-30 21:28:54 +00:00
def get_tbl_names ( db_name )
results = mssql_query ( " SELECT name,id FROM #{ db_name } ..sysobjects WHERE xtype = 'U' " ) [ :rows ]
return results
end
# TODO: This should be split up, I fear nil problems in these query/response parsings
def get_columns ( db_name , table_id )
results = mssql_query ( " Select syscolumns.name,systypes.name,syscolumns.length from #{ db_name } ..syscolumns JOIN #{ db_name } ..systypes ON syscolumns.xtype=systypes.xtype WHERE syscolumns.id= #{ table_id } " ) [ :rows ]
return results
end
2012-01-10 23:32:09 +00:00
end