For the complete documentation index, see llms.txt. This page is also available as Markdown.
AV-EVASIONDLL-HIJACKINGKIOSKWINDOWSWINDOWS-PRIVESC

Kiosk

Challenge Lab (Medium) - by Ryan Yager

The following post by 0xb0b is licensed under CC BY 4.0


Scenario

Objective

DarkHaven is deploying a new Virtual Desktop Infrastructure (VDI) to harden their corporate network. You have been engaged to assess the security of their VDI portal and underlying architecture. Your primary objective is to identify vulnerabilities that could allow an authenticated user to escape the virtualized environment and escalate privileges.

Summary

Summary

In Kiosk, we begin with external enumeration and discover an IIS web server on port 80, a second web interface on port 8443, SMB on 445, RDP on 3389, and WinRM on 5985. The 8443 interface presents a login page, and robots.txtadvertises /portal.asp, /admin/, and /api/ endpoints. Directory brute-forcing yields no additional findings, so we focus on the login form, bypassing authentication via a classic SQL injection payload (' -- -) and recovering credentials for vdiuser.

Logging in via RDP as vdiuser brings us in a kiosk environment that is able to open remote files. We set up a credentialed SMB share and serve a custom Go stager that downloads and executes Sliver C2 shellcode directly into memory via VirtualAlloc. Providing the stager path through the kiosk's UNC path input triggers execution and returns a Sliver session, granting us a foothold on the system.

For privilege escalation to svcuser, we run SharpUp and discover plaintext credentials embedded in a Unattend.xmldeployment file at C:\Windows\Panther\. Using these credentials, we RDP in as svcuser and are greeted with another Kiosk environment. By entering C:\Windows\system32\cmd.exe directly into the address bar of the open file dialog, we open the file explorer, and repeating the same trick in its address bar allows us to escape the Kiosk and spawn a command prompt.

With access as svcuser we recall the unquoted service path C:\Program Files\Darkhaven Kiosk Services\. We plant a service-aware Go stager compiled as DH.exe,modified to handle SCM control requests and execute shellcode asynchronously, into the vulnerable path. Restarting the DH_KioskMonitor service triggers execution in the context of dh_admin, yielding a stable Sliver session.

Finally, enumerating the C:\DarkhavenTools\ directory reveals a scheduled task executable with a missing dhlog.dlldependency. We craft a malicious DLL that executes within DllMain on DLL_PROCESS_ATTACH and place it at the expected path. The scheduled task runs as Administrator, and our DLL payload creates a new local administrator account, allowing us to RDP in and retrieve the final flag.

Changelog

The scenario has been changed to an assumed breach scenarion. The section access as vdiuser can be skipped.

Recon

We use rustscan -b 500 -a 10.0.24.230 --top -- -sC -sV -Pn to enumerate all TCP ports on the target machine, piping the discovered results into Nmap which runs default NSE scripts -sC, service and version detection -sV, and treats the host as online without ICMP echo -Pn.

A batch size of 500 trades speed for stability, the default 1500 balances both, while much larger sizes increase throughput but risk missed responses and instability.

The target machine exposes six open ports: HTTP/IIS on 80 and 8443 (SSL, hostname darkhaven-vdi.corp), SMB on 445, RDP on 3389, WinRM on 5985, and HTTPAPI on 5357. The target is a Windows Server 2019 machine (hostname EC2AMAZ-0536LUM) with the 8443 web interface notably advertising /portal.asp, /admin/, and /api/ endpoints via the robots.txt.

We try to authenticate anonymously and via guest agains SMB using NetExec but without success.

On port 80, we only have the standard IIS page available.

When we visit the site on port 8443, we are presented with a login page.

A directory scan using FeroxBuster does not reveal any additional information beyond what we already identified with our port scan.

Access as vdiuser [deprecated]

Credentials are given. Skip to Shell as vdiuser

We'll focus on the login page and try to gain access using a simple SQL injection payload. Using ' -- - as the username with any password, we can attempt to comment out the remainder of the SQL query to bypass the authentication if the login form is vulnerable to unsanitized input.

We get access and see the credentials for the VDI Desktop.

Shell as vdiuser

Using the credentials we are able to log in via RDP to the VDI. This looks like a Kiosk mode. From there we can provide a local or network path to open a document.

First, we'll set up an SMB server. The idea is to see if we can access our machine by specifying a UNC path, so that we can transfer for example files, get maybe out of the kiosk mode through a file explorer popping up.

We provide the path to our share.

And receive a connection. But nothing pops up.

Now lets see if the application opens any file we provide and is capable of executing provided executables.

We're bringing out the big guns and prepare a stager to download and execute Sliver C2 shellcode tro retrieve a session in Sliver C2.

Prepare a custom stager

First we need to prepare the stager. This is the one we created for the lab Staged:

The stager fetches raw shellcode from a chosen URL and loads it directly into memory as bytes. The payload is not embedded in the binary, allowing it to be changed without recompiling.

It calls VirtualAlloc to reserve and commit memory with execute, read, and write permissions, then copies the downloaded shellcode into that memory using unsafe pointer operations.

The execution is transferred to the allocated memory address using syscall.Syscall, handing control to the shellcode.

We compile the stager as follows on our exegol instance like we did for Dismay:

We compile the stager as follows on our exegol instance:

The addition of -ldflags="-H windowsgui" ensures that we compile it as an application and not a console app, so it wont spawn a terminal.

Since the stager got caught due to sample submission, but want to reuse it, we use a simple trick and use the -s -w ldflags for compilation. Using -s -w strips debug symbols and DWARF metadata from the Go binary, changing its hash and reducing recognizable signatures, which can help avoid detection because antivirus engines that previously flagged the original sample submission may no longer match the modified compiled file exactly. We might see this neat trick later again.

Generate shell code

During generation without the -G tag, which disables the encoder, no shellcode could be successfully generated. The resulting shellcode was always empty. This may be related to the underlying architecture on which I am operating, namely ARM:

https://github.com/BishopFox/sliver/issues/1114

Next, we need run the Sliver server and generate the shell code to connect to our sliver instance.

We do this as follows:

We run a web server from which the stager and the shellcode can be fetched.

Setup listener

We set up the listener in sliver as follows:

Next we provide our stager and get an error. Authentication is required.

We start up our SMB server again, this time with the credentials of vdiuser.

We provide the stager again and get an execution prompt. We run it.

This may take a little while.

After a short duration we see the shellcode downloaded and retrieve a session in Sliver C2. We interact with is as follows:

We do now have access to the system.

The C: drive contains some interesting folders including KioskData and VDIData. The VDIData folder holds the first flag.

Alternative Escape

There should be many other approaches possible.

This is one spotted by DKob on QA:

We can open the context menu through a right click and select print and chose to print a PDF to the file system. This would allow us to open the file explorer and from the open a terminal.

After selecting Print... from the context menu we chose Print to PDF and select Print again.

The file explorer opens to save the PDF...

Instead of chosing a file name we submit the following path pointing to cmd.exe in the address bar and the terminal gets opened.

Shell as svcuser

We enumerate the target using sharpup. It is a .NET port of PowerUp available through the Sliver C2 armory.

With the audit parameter we are abel to run a holistic check.

We are able to find an unattend.xml file containing potentially sensitive deployment credentials left over from the initial setup, and an unquoted service path. This is a misconfiguration that may allow us to escalate our privileges by planting our stager in a vulnerable path location and run it in the context of the service user if we are able to control the service.

However, upon further testing, it turns out that we cannot query the services with the current user and are not able to write to the path.

Let's take a look at the Unattend.xml file, where we'll find the credentials for user svcuser in a base64 encoded string.

We decode it using CyberChef.

We try to get a remote desktop session as svcuser and are successful. We are again in a Kiosk environment.

We browse for local files and try to open a terminal by entering the following path, but a file explorer pops up to chose a file to upload.

We enter the path again in the address bar of file explorer, which allows us to open a terminal and exit Kiosk mode.

From there we are able to reach out to the second flag at C:\Users\svcuser\Desktop\flag.txt.

Shell as dh_admin

Recalling the results from sharpup and the fact that we are the svcuser we might have now the permissions to query the services.

Running icacls against the service directory reveals the effective permissions and we see that we are able to write to this path as the svcuser. This allows us to replace the executable or abuse the unqouted service path by placing the stager in C:\Program Files\Darkhaven Kiosk Services\DH.exe for exampe.

Recalling that we were not able to query for the service as vdiuser...

... but we are now able to as svcuser.

We switch to a powershell session. Move to the upper service directory and download our stager as DH.exe.

We stop and run the service...

... and receive a connection. We are dh_admin.

However, since our stager is not an actual service and is unresponsive to start or control requests, it will receive a timeout and be terminated after running the shellcode.

We use Claude to create a rough service boiler plate...

We need to change the executeShellcode function so it makes the execution asynchronous so it returns immediately instead of blocking while the shellcode runs.

We end up with the following stager after applying the changes.

We compile the stager.

Next, we repeat our steps uploading the new stager binary to the vulnerable unquoted service path location. Upon service restart, the SCM should resolve the ambiguous path and executes our stager.

We start the service...

... and receive a session. The service does not get terminated and we have a stable session.

At C:/Users/dh_admin/Desktop/flag3.txt we find the third flag.

Shell as Administrator

We enumerate the C: drive again.

Here we have also a DarkhavenTools directory which contains an executable and a corresponding log folder. The log reveals that on execution thee dhlog.dll was missing. We might be able to DLL hijack the executable which is run by a scheduled task.

We prepare a DLL that executes the whoami command and places the output into a file at C:\DarkhavenTools\output.txt to see if our hijack was successful.

It executes the payload directly within DllMain when loaded into a process via the DLL_PROCESS_ATTACH event, avoiding thread creation which could trigger security detections.

We compile the poc as follows...

... and ulpoad the dll into C:\DarkhavenTools\logs\dhlog.dll as derived from the logs.

After a short duration we see the output.txt file created. It was run by the administrator.

In my case, I was unable to download and execute my stager. As an alternative, we create a user with local administrator privileges who is a member of the Remote Management Users and Remote Desktop Users group.

We check if the users exists and see it sucessfully created.

We are able to log in with our created user using RDP and run an elevated terminal. From there we are able to reach out to the final flag at C:\Users\Administrator\Desktop\flag4.txt.

Last updated