En esta tarea, tienes que ejecutar la alerta añadiendo un post. En este juego, es DOM XSS, pero cuando se pruebe en aplicaciones reales de chat/comentarios, será un XSS almacenado.
Ok echemos un vistazo a la fuente y al mensaje anterior también.
Al inspeccionar la fuente, puedes ver que el mensaje por defecto utiliza diferentes tipos de etiquetas html para darle estilo. Esa es nuestra clave.
Revisa la fuente para confirmarlo. Así es como se renderiza nuestro post
Puedes ver que el post no pasa por ningún filtro. Así que podemos utilizar cualquiera de los métodos mencionados anteriormente.
<a href="javascript:alert()">Link</a>
<img src=X onerror="alert()">
Y así sucesivamente.
Felicidades. Has completado el nivel 2. Ahora avanza al siguiente nivel.
Tarea 3 : Esa sensación de hundimiento
Esta es muy diferente de las 2 que hemos completado. Aquí, tenemos que aprender sobre window.location.hash.
Es la parte que viene después del símbolo #
y se utiliza para la navegación en la página. Es una característica del navegador y funcionará incluso sin JavaScript.
Inspeccionemos el código fuente de éste.
La parte interesante en el código es
var html = "Image " + parseInt(num) + "<br>"; html += "<img src='https://medium.com/static/level3/cloud" + num + ".jpg' />";
num
contiene el valor de window.location.hash
y se utiliza en 2 lugares. En primer lugar, se utiliza dentro de la función parseInt por lo tanto nuestra carga útil no funcionará allí. Pero en la siguiente línea, se utilizan los datos en bruto. Ahí es donde vamos a inyectar nuestra carga útil.
Así que tenemos que cerrar una sola cuota '
allí y tenemos que inyectar nuestra carga útil.
Puedes probar cualquier payload dentro de ' '
Después de #
Intenta poner cualquiera de los siguientes después de #
y visita la url.
1' onerror='alert()
1'><img src=X onerror="alert()">'
1'><script>alert()</script>'
1'><a href="javascript:alert()">Link</a>'
Y así sucesivamente.
Genial. Ahora podemos avanzar al siguiente nivel.
Tarea 4 : El contexto importa
Tenemos un espacio para introducir la duración del temporizador. Ahí es donde vamos a explotar.
Revisemos el código fuente.
En timer.html, podemos ver esta línea
<img src="https://medium.com/static/loading.gif" onload="startTimer('{{ timer }}');" />
Tenemos que explotar en la expresión {{ timer }}
Pero está colocada dentro de una función startTimer('');
que es un manejador del evento onload
. El punto principal a tener en cuenta es que el atributo de controlador de eventos en HTML aceptar múltiples funciones de devolución de llamada.
Así que tenemos que cerrar la función y ejecutar nuestra alerta allí. Tenga en cuenta que, el valor no pasó a través de una función parseInt
en lugar de los datos en bruto se utiliza. Así que podemos cerrar la función añadiendo un ');
y luego inyectar nuestro alert
. Dado que se utiliza como inline, no podemos inyectar alert();
allí porque romperá las cosas. La declaración se convertirá en onload="startTimer('3'); alert();')"
y no funcionará.
Así que tenemos que añadir un patrón que mantenga el patrón sin romper. Añade alert('
y es suficiente.
Así que nuestro payload será
3');alert('
Pulsando el botón de inicio del temporizador se ejecutará la alerta y habremos terminado este nivel.
Avanzar a la siguiente tarea.
Tarea 5 : Breaking Protocol
En la página de inicio, no tenemos forma de inyectar nada. Todo lo que tenemos es un enlace. Así que vamos a hacer clic en él.
Aquí, podemos ver 2 lugares para inyectar nuestro payload. uno en la propia url y otro en el cuadro de entrada. El cuadro de entrada es un lugar para introducir el correo electrónico y esperar que no se refleje en otro lugar. Así que vamos a la primera. En la url.
Inspecciona el código fuente de la página actual, que es signup.html y podemos ver la línea
<a href="{{ next }}">Next >></a>
Gran lugar para inyectar un payload. Nuestro payload se establecerá como el valor del atributo href
en una etiqueta a
. Si somos capaces de añadir javascript:alert()
podremos ejecutar nuestro payload. Ahora vamos a ver cuál es el valor de next
. No encontramos ninguno en la página. ¿Dónde lo buscamos?
Código Python al rescate. Revisa level.py y veremos
if "signup" in self.request.path: self.render_template('signup.html', {'next': self.request.get('next')})
Así que se utilizará el valor de next
en la url.
Cambia el valor de next
en la url de confirm
a javascript:alert()
y la url final quedará como
Now clicking on Next >> in the page will trigger our payload.
We now completed level 5. And 1 level remains.
Task 6 : Follow the 🐇
There is a path to a js file in the url.
Let’s inspect the source code. In page index.html, you can see a function includeGadget
y dentro del cuerpo de la función, puedes ver el siguiente código.
var scriptEl = document.createElement('script');
Así que podemos cargar archivo js externo pero no desde una url http
o https
.
Aquí, vamos a probar con las urls data
.
Las urls de datos tienen la forma data:{type},content
Así que cambia el valor después de #
a
data:application/javascript,alert()
o a
data:text/plain,alert()
y podremos ejecutar el alert
.
Aquí tienes un vídeo de resolución del Juego.