Hack The Box - HTB Touch Writeup - Easy - Weekly - september 3th, 2026
## Overview
* **Target IP:** `10.129.xx.xx`
* **Attacker (VPN) IP:** `10.10.xx.xx`
* **Supplied credentials:** `Jenny Crawford / KS7X2M`
The box is themed around a fictional airline check-in kiosk ("HTB Airways"). The attack surface combines a device-management web portal (Nexion DeviceHub), a tightly restricted Windows kiosk session, and a locally running MySQL 8.0 instance that is ultimately turned into SYSTEM-level code execution through a User Defined Function (UDF).
* * *
## 1. Reconnaissance — Nmap
nmap -sV -sC 10.129.xx.xx
Starting Nmap 7.99 ( https://nmap.org ) at 2026-10-04 02:03 +0000
Nmap scan report for 10.129.xx.xx
Host is up (0.35s latency).
Not shown: 996 filtered tcp ports (no-response)
PORT STATE SERVICE VERSION
135/tcp open msrpc Microsoft Windows RPC
3389/tcp open ms-wbt-server Microsoft Terminal Service
5985/tcp open http Microsoft HTTPAPI httpd 2.0 (SSDP/UPnP)
|_http-title: Not Found
|_http-server-header: Microsoft-HTTPAPI/2.0
8443/tcp open http Microsoft HTTPAPI httpd 2.0 (SSDP/UPnP)
|_http-server-header: Microsoft-HTTPAPI/2.0
|_http-cors: GET POST PUT OPTIONS
|_http-trane-info: Problem with XML parsing of /evox/about
| http-title: Nexion DeviceHub - Login
|_Requested resource was /login
Service Info: OS: Windows; CPE: cpe:/o:microsoft:windows
What the open ports tell us:
* **135** — MSRPC
* **3389** — RDP (Terminal Services)
* **5985** — WinRM (the banner reads as a generic HTTPAPI service, but this is the usual WinRM port)
* **8443** — a web application: the Nexion DeviceHub login page
Seeing RDP and WinRM exposed alongside a management web portal is a strong hint that the portal might hand us credentials or device details we can then reuse against the other services — the familiar HTB pattern of linking one service into the next.
* * *
## 2. Web Enumeration on Port 8443
Visiting `https://10.129.xx.xx:8443` presents a Nexion DeviceHub login screen that expects a device password we don't yet possess.
### Directory / Content Discovery
ffuf -u http://10.129.xx.xx:8443/FUZZ -w /usr/share/wordlists/dirb/common.txt
The first pass was almost entirely noise — every path returned a default `302` redirect (wildcard-style behaviour), so the output needed filtering:
ffuf -u http://10.129.xx.xx:8443/FUZZ -w /usr/share/wordlists/dirb/common.txt -fc 302
api [Status: 403, Size: 35, Words: 2, Lines: 1, Duration: 279ms]
favicon.ico [Status: 200, Size: 452, Words: 37, Lines: 1, Duration: 283ms]
login [Status: 200, Size: 3572, Words: 122, Lines: 3, Duration: 280ms]
An `/api` path that answered with `403 Forbidden` (as opposed to `404`) signalled that the endpoint is real but gated — it wants auth, or a more specific sub-path. That justified fuzzing a level deeper:
ffuf -u http://10.129.xx.xx:8443/api/FUZZ -w /usr/share/wordlists/dirb/common.txt -fc 302
[Status: 403, Size: 35, Words: 2, Lines: 1, Duration: 293ms]
scan [Status: 405, Size: 30, Words: 3, Lines: 1, Duration: 524ms]
status [Status: 200, Size: 116, Words: 3, Lines: 1, Duration: 414ms]
* `/api/scan` → `405 Method Not Allowed` (GET is the wrong verb here — most likely a POST endpoint; not worth chasing since it needs auth anyway)
* `/api/status` → `200 OK` — and this one gives up data with no authentication at all
### Unauthenticated Info Leak: `/api/status`
curl http://10.129.xx.xx:8443/api/scan | jq
{
"error": "Method not allowed"
}
curl http://10.129.xx.xx:8443/api/status | jq
{
"device": "Nexion DeviceHub DH-100",
"serial": "NX-DH-2024-B7042",
"firmware": "1.4.2",
"status": "online",
"uptime": 33838
}
Here's the flaw: an unauthenticated endpoint hands out the device serial number, and that serial doubles as the DeviceHub login password. Using a device identifier as a secret is a textbook "serial-as-password" mistake — anyone who can reach `/api/status` walks away with the credential to the admin portal.
Entering the serial `NX-DH-2024-B7042` as the device password on `/login` succeeded, dropping us into the DeviceHub dashboard.
* * *
## 3. Exploring the DeviceHub Dashboard
Inside, the dashboard listed two managed devices, both active:
* Passport Scanner
* Boarding Pass Printer
The portal let us toggle these devices on and off remotely, and it also surfaced a stored credential pair tied to the kiosk hardware:
KioskUser : [REDACTED - KIOSKUSER PASSWORD]
Some context: a _kiosk user_ is a restricted local account set up so an unauthenticated or limited person can use just one designated application (think of an airport check-in terminal). The name strongly suggests this credential belongs to a locked-down local Windows account rather than anything privileged.
* * *
## 4. Credential Validation — Testing for Reuse Across Services
Because Nmap had already shown WinRM (5985) and RDP (3389) listening, the obvious move was to see whether the leaked `KioskUser` credential had been reused on either. This is standard credential-reuse / stuffing testing; each attempt is shown below.
### WinRM check
nxc winrm 10.129.xx.xx -u KioskUser -p '[REDACTED - KIOSKUSER PASSWORD]'
WINRM 10.129.xx.xx 5985 KIOSK-042 [*] Windows 11 / Server 2025 Build 26100 (name:KIOSK-042) (domain:KIOSK-042)
WINRM 10.129.xx.xx 5985 KIOSK-042 [-] KIOSK-042\KioskUser:[REDACTED - KIOSKUSER PASSWORD]
Outcome: rejected (`[-]`). WinRM turned the pair away — most likely because this local account isn't permitted to use WinRM, not because the password is wrong (confirmed via RDP shortly).
### RDP check
nxc rdp 10.129.xx.xx -u KioskUser -p '[REDACTED - KIOSKUSER PASSWORD]'
RDP 10.129.xx.xx 3389 10.129.xx.xx [*] Probably old, doesn't not support HYBRID or HYBRID_EX (nla:False)
RDP 10.129.xx.xx 3389 10.129.xx.xx [-] None\KioskUser:[REDACTED - KIOSKUSER PASSWORD] (Server refused our connection request! Reason: SSL_NOT_ALLOWED_BY_SERVER)
This one failed on a TLS/NLA negotiation problem (`SSL_NOT_ALLOWED_BY_SERVER`) rather than a bad credential, so we switched from the NetExec check to a full RDP client.
### Successful RDP login via xfreerdp3
xfreerdp3 /v:10.129.xx.xx /u:KioskUser /p:'[REDACTED - KIOSKUSER PASSWORD]' /cert:ignore /dynamic-resolution +clipboard
This connected and placed us in a graphical Windows session as `KioskUser`, proving the leaked credential was valid and that the earlier WinRM rejection was down to WinRM-specific restrictions, not a wrong password.
* * *
## 5. Kiosk Breakout — Forcing an Application Error to Reach a Shell
The RDP session dropped us into a heavily restricted kiosk application offering two paths:
* **Self check-in** — the first step accepted the supplied credentials (`Jenny Crawford / KS7X2M`), but the second step demanded a passport scan (a physical action we couldn't perform).
* **Staff login** — required scanning an employee badge (again, hardware we didn't have).
Neither flow could finish the normal way, which pointed straight at a classic kiosk-breakout idea: deliberately make the kiosk app throw an unhandled error, since the error handler often exposes an embedded browser (Edge/IE) or a file dialog that can be turned into a real desktop shell.
The crucial observation: the DeviceHub portal on 8443 let us power the Passport Scanner and Boarding Pass Printer _off_. If the kiosk relies on those devices being online to complete a scan, taking them offline should make the scan step fail with an error.
### Breakout steps
1. From the DeviceHub dashboard (8443), power off both the Passport Scanner and the Boarding Pass Printer.
2. In the kiosk, pick **Staff login → Scan badge**. With the scanner now offline, this raises an application error dialog containing a clickable link/details.
3. Click the link in the dialog — this opens Microsoft Edge.
4. In Edge, hit **Ctrl+O** to summon the native Open File dialog — a common kiosk-escape trick, since the file picker is effectively a full Explorer window.
5. Browse to `C:\Windows\System32\`, find `cmd.exe`, and open it.
6. Owing to how the restricted shell treats the action, it first downloads `cmd.exe` and then runs it — handing us a working Command Prompt inside the kiosk session.
This is the canonical kiosk/browser-restriction bypass: provoke an error → the handler launches a full browser → the browser's native file dialog becomes a side door into the filesystem → run `cmd.exe` from there.
* * *
## 6. Reverse Shell as `KioskUser`
With a Command Prompt in hand, we built a reverse shell and moved it onto the target.
### This post is for subscribers only
Become a member to get access to all content
Subscribe now