Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
rapid7
GitHub Repository: rapid7/metasploit-framework
Path: blob/master/modules/auxiliary/admin/mssql/mssql_idf.rb
19516 views
1
##
2
# This module requires Metasploit: https://metasploit.com/download
3
# Current source: https://github.com/rapid7/metasploit-framework
4
##
5
6
##
7
# Author: Robin Wood <[email protected]> <http://www.digininja.org>
8
# Version: 0.1
9
#
10
# This module will search the specified MSSQL server for
11
# 'interesting' columns and data
12
#
13
##
14
15
class MetasploitModule < Msf::Auxiliary
16
include Msf::Exploit::Remote::MSSQL
17
include Msf::OptionalSession::MSSQL
18
19
def initialize(info = {})
20
super(
21
update_info(
22
info,
23
'Name' => 'Microsoft SQL Server Interesting Data Finder',
24
'Description' => %q{
25
This module will search the specified MSSQL server for
26
'interesting' columns and data.
27
28
This module has been tested against the latest SQL Server 2019 docker container image (22/04/2021).
29
},
30
'Author' => [ 'Robin Wood <robin[at]digininja.org>' ],
31
'License' => MSF_LICENSE,
32
'References' => [
33
[ 'URL', 'http://www.digininja.org/metasploit/mssql_idf.php' ],
34
],
35
'Notes' => {
36
'Stability' => [CRASH_SAFE],
37
'SideEffects' => [IOC_IN_LOGS],
38
'Reliability' => []
39
}
40
)
41
)
42
43
register_options(
44
[
45
OptString.new('NAMES', [ true, 'Pipe separated list of column names', 'passw|bank|credit|card']),
46
]
47
)
48
end
49
50
def print_with_underline(str)
51
print_line(str)
52
print_line('=' * str.length)
53
end
54
55
def run
56
headings = [
57
['Database', 'Schema', 'Table', 'Column', 'Data Type', 'Row Count']
58
]
59
60
sql = ''
61
sql += 'DECLARE @dbname nvarchar(255), @id int, @sql varchar (4000); '
62
sql += 'DECLARE table_cursor CURSOR FOR SELECT name FROM sys.databases '
63
sql += 'OPEN table_cursor '
64
sql += 'FETCH NEXT FROM table_cursor INTO @dbname '
65
sql += 'WHILE (@@FETCH_STATUS = 0) '
66
sql += 'BEGIN '
67
sql += "SET @sql = 'select ';"
68
sql += "SET @sql = @sql + ' ''' + @dbname + ''' as ''Database'', ';"
69
sql += "SET @sql = @sql + 'sys.schemas.name as ''Schema'', ';"
70
sql += "SET @sql = @sql + 'sys.objects.name as ''Table'', ';"
71
sql += "SET @sql = @sql + 'sys.columns.name as ''Column'', ';"
72
sql += "SET @sql = @sql + 'sys.types.name as ''Column Type'' ';"
73
sql += "SET @sql = @sql + 'from ' + @dbname + '.sys.columns ';"
74
sql += "SET @sql = @sql + 'inner join ' + @dbname + '.sys.objects on sys.objects.object_id = sys.columns.object_id ';"
75
sql += "SET @sql = @sql + 'inner join ' + @dbname + '.sys.types on sys.types.user_type_id = sys.columns.user_type_id ';"
76
sql += "SET @sql = @sql + 'inner join ' + @dbname + '.sys.schemas on sys.schemas.schema_id = sys.objects.schema_id ';"
77
78
list = datastore['Names']
79
where = "SET @sql = @sql + ' WHERE ("
80
list.split(/\|/).each do |val|
81
where += " lower(sys.columns.name) like ''%" + val + "%'' OR "
82
end
83
84
where.slice!(-3, 4)
85
86
where += ") ';"
87
88
sql += where
89
90
sql += "SET @sql = @sql + 'and sys.objects.type=''U'';';"
91
sql += 'EXEC (@sql);'
92
sql += 'FETCH NEXT FROM table_cursor INTO @dbname '
93
sql += 'END '
94
sql += 'CLOSE table_cursor '
95
sql += 'DEALLOCATE table_cursor '
96
97
begin
98
if session
99
set_mssql_session(session.client)
100
else
101
unless mssql_login_datastore
102
print_error('Login failed')
103
return
104
end
105
end
106
result = mssql_query(sql, false)
107
rescue Rex::ConnectionRefused => e
108
print_error("Connection failed: #{e}")
109
return
110
end
111
112
column_data = result[:rows]
113
widths = [0, 0, 0, 0, 0, 9]
114
total_width = 0
115
116
if result[:errors] && !result[:errors].empty?
117
result[:errors].each do |err|
118
print_error(err)
119
end
120
end
121
122
if column_data.nil?
123
print_error("No columns matched the pattern #{datastore['NAMES'].inspect}. Set the NAMES option to change this search pattern.")
124
return
125
end
126
127
(column_data | headings).each do |row|
128
0.upto(4) do |col|
129
widths[col] = row[col].length if row[col].length > widths[col]
130
end
131
end
132
133
widths.each do |a|
134
total_width += a
135
end
136
137
print_line
138
139
buffer = ''
140
headings.each do |row|
141
0.upto(5) do |col|
142
buffer += row[col].ljust(widths[col] + 1)
143
end
144
print_line(buffer)
145
print_line
146
buffer = ''
147
148
0.upto(5) do |col|
149
buffer += print '=' * widths[col] + ' '
150
end
151
print_line(buffer)
152
print_line
153
end
154
155
column_data.each do |row|
156
count_sql = 'SELECT COUNT(*) AS count FROM '
157
158
full_table = ''
159
column_name = ''
160
buffer = ''
161
0.upto(4) do |col|
162
full_table += row[col] + '.' if col < 3
163
column_name = row[col] if col == 3
164
buffer += row[col].ljust(widths[col] + 1)
165
end
166
full_table.slice!(-1, 1)
167
count_sql += full_table
168
169
result = mssql_query(count_sql, false) if mssql_login_datastore
170
171
count_data = result[:rows]
172
row_count = count_data[0][0]
173
174
buffer += row_count.to_s
175
print_line(buffer)
176
print_line
177
end
178
179
print_line
180
disconnect
181
end
182
end
183
184