CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutSign UpSign In
rapid7

CoCalc provides the best real-time collaborative environment for Jupyter Notebooks, LaTeX documents, and SageMath, scalable from individual users to large groups and classes!

GitHub Repository: rapid7/metasploit-framework
Path: blob/master/modules/auxiliary/scanner/mssql/mssql_schemadump.rb
Views: 1904
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 => 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
tmp_db = {}
85
tmp_tblnames = get_tbl_names(dbname[0])
86
unless tmp_tblnames.nil?
87
tmp_db['DBName']= dbname[0]
88
tmp_db['Tables'] = []
89
tmp_tblnames.each do |tblname|
90
next if tblname[0].nil?
91
tmp_tbl = {}
92
tmp_tbl['TableName'] = tblname[0]
93
tmp_tbl['Columns'] = []
94
tmp_columns = get_columns(dbname[0], tblname[1])
95
unless tmp_columns.nil?
96
tmp_columns.each do |column|
97
next if column[0].nil?
98
tmp_column = {}
99
tmp_column['ColumnName'] = column[0]
100
tmp_column['ColumnType'] = column[1]
101
tmp_column['ColumnLength'] = column[2]
102
tmp_tbl['Columns'] << tmp_column
103
end
104
end
105
tmp_db['Tables'] << tmp_tbl
106
end
107
end
108
mssql_schema << tmp_db
109
end
110
end
111
return mssql_schema
112
end
113
114
115
# Gets all of the Databases on this Instance
116
def get_db_names
117
results = mssql_query(mssql_db_names())[:rows]
118
return results
119
end
120
121
# Gets all the table names for the given DB
122
def get_tbl_names(db_name)
123
results = mssql_query("SELECT name,id FROM #{db_name}..sysobjects WHERE xtype = 'U'")[:rows]
124
return results
125
end
126
127
# TODO: This should be split up, I fear nil problems in these query/response parsings
128
def get_columns(db_name, table_id)
129
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]
130
return results
131
end
132
end
133
134