Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
rapid7
GitHub Repository: rapid7/metasploit-framework
Path: blob/master/modules/auxiliary/scanner/mssql/mssql_schemadump.rb
19721 views
1
##
2
# This module requires Metasploit: https://metasploit.com/download
3
# Current source: https://github.com/rapid7/metasploit-framework
4
##
5
require 'yaml'
6
7
class MetasploitModule < Msf::Auxiliary
8
include Msf::Exploit::Remote::MSSQL
9
include Msf::Auxiliary::Report
10
include Msf::Auxiliary::Scanner
11
include Msf::OptionalSession::MSSQL
12
13
def initialize
14
super(
15
'Name' => 'MSSQL Schema Dump',
16
'Description' => %Q{
17
This module attempts to extract the schema from a MSSQL Server
18
Instance. It will disregard builtin and example DBs such
19
as master, model, msdb, and tempdb. The module will create
20
a note for each DB found, and store a YAML formatted output
21
as loot for easy reading.
22
},
23
'Author' => ['theLightCosine'],
24
'License' => MSF_LICENSE
25
)
26
27
register_options([
28
OptBool.new('DISPLAY_RESULTS', [true, "Display the Results to the Screen", true])
29
])
30
end
31
32
def run_host(ip)
33
if session
34
set_mssql_session(session.client)
35
else
36
unless mssql_login_datastore
37
print_error("#{datastore['RHOST']}:#{datastore['RPORT']} - Invalid SQL Server credentials")
38
return
39
end
40
end
41
42
# Grabs the Instance Name and Version of MSSQL(2k,2k5,2k8)
43
instance_info = mssql_query(mssql_enumerate_servername())[:rows][0][0].split('\\')
44
instancename = instance_info[1] || instance_info[0]
45
46
print_status("Instance Name: #{instancename.inspect}")
47
version = mssql_query(mssql_sql_info())[:rows][0][0]
48
output = "Microsoft SQL Server Schema \n Host: #{mssql_client.peerhost} \n Port: #{mssql_client.peerport} \n Instance: #{instancename} \n Version: #{version} \n====================\n\n"
49
50
# Grab all the DB schema and save it as notes
51
mssql_schema = get_mssql_schema
52
if mssql_schema.nil? or mssql_schema.empty?
53
print_good output if datastore['DISPLAY_RESULTS']
54
print_warning('No schema information found')
55
return nil
56
end
57
mssql_schema.each do |db|
58
report_note(
59
:host => mssql_client.peerhost,
60
:type => "mssql.db.schema",
61
:data => { :database => db },
62
:port => mssql_client.peerport,
63
:proto => 'tcp',
64
:update => :unique_data
65
)
66
end
67
output << YAML.dump(mssql_schema)
68
this_service = report_service(
69
:host => mssql_client.peerhost,
70
:port => mssql_client.peerport,
71
:name => 'mssql',
72
:proto => 'tcp'
73
)
74
store_loot('mssql_schema', "text/plain", mssql_client.peerhost, output, "#{mssql_client.peerhost}_mssql_schema.txt", "MS SQL Schema", this_service)
75
print_good output if datastore['DISPLAY_RESULTS']
76
end
77
78
def get_mssql_schema
79
mssql_db_names = get_db_names()
80
mssql_schema = []
81
unless mssql_db_names.nil?
82
mssql_db_names.each do |dbname|
83
next if dbname[0] == 'model' or dbname[0] == 'master' or dbname[0] == 'msdb' or dbname[0] == 'tempdb'
84
85
tmp_db = {}
86
tmp_tblnames = get_tbl_names(dbname[0])
87
unless tmp_tblnames.nil?
88
tmp_db['DBName'] = dbname[0]
89
tmp_db['Tables'] = []
90
tmp_tblnames.each do |tblname|
91
next if tblname[0].nil?
92
93
tmp_tbl = {}
94
tmp_tbl['TableName'] = tblname[0]
95
tmp_tbl['Columns'] = []
96
tmp_columns = get_columns(dbname[0], tblname[1])
97
unless tmp_columns.nil?
98
tmp_columns.each do |column|
99
next if column[0].nil?
100
101
tmp_column = {}
102
tmp_column['ColumnName'] = column[0]
103
tmp_column['ColumnType'] = column[1]
104
tmp_column['ColumnLength'] = column[2]
105
tmp_tbl['Columns'] << tmp_column
106
end
107
end
108
tmp_db['Tables'] << tmp_tbl
109
end
110
end
111
mssql_schema << tmp_db
112
end
113
end
114
return mssql_schema
115
end
116
117
# Gets all of the Databases on this Instance
118
def get_db_names
119
results = mssql_query(mssql_db_names())[:rows]
120
return results
121
end
122
123
# Gets all the table names for the given DB
124
def get_tbl_names(db_name)
125
results = mssql_query("SELECT name,id FROM #{db_name}..sysobjects WHERE xtype = 'U'")[:rows]
126
return results
127
end
128
129
# TODO: This should be split up, I fear nil problems in these query/response parsings
130
def get_columns(db_name, table_id)
131
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]
132
return results
133
end
134
end
135
136