Saltar al contenido
Open Security
Ciberseguridad PrácticaInicial· 30 min

XSS local defensivo: source, sink y output encoding

Un lab local para entender XSS sin tocar sitios ajenos: de dónde entra el dato, dónde se interpreta como HTML y cómo cortarlo con APIs seguras.

#xss#web#defensivo

Antes de empezar necesitás

  • Un navegador moderno
  • Una terminal con Python 3 opcional para servir archivos locales

Al terminar vas a poder

  • Distinguir source, sink y contexto
  • Ver por qué innerHTML con input no confiable es peligroso
  • Aplicar textContent como mitigación simple
  • Documentar el bug y el fix sin atacar terceros

XSS no es “pegar un script en una web”. Es un bug de contexto: un dato que debía ser tratado como texto termina siendo interpretado como HTML o JavaScript. En este lab lo ves en local, sin tocar sitios ajenos.

Página vulnerable de juguete

Creá un archivo local xss-demo.html con una idea como esta:

<div id="saludo"></div>
<script>
  const params = new URLSearchParams(location.search);
  const name = params.get("name") ?? "mundo";
  document.querySelector("#saludo").innerHTML = `Hola ${name}`;
</script>

El source es location.search. El sink es innerHTML. El problema es que innerHTML interpreta HTML.

vt@labs:~/xss-local
python3 -m http.server 8000

Abrí http://localhost:8000/xss-demo.html?name=Valen y después probá un valor con etiquetas HTML. No uses sitios de terceros: esto es tu archivo local.

El fix mínimo

Si querés mostrar texto, usá una API que escriba texto:

<script>
  const params = new URLSearchParams(location.search);
  const name = params.get("name") ?? "mundo";
  document.querySelector("#saludo").textContent = `Hola ${name}`;
</script>

Ahora el navegador no interpreta el contenido como HTML: lo muestra como texto.

Evidencia esperada

Documentá el bug con esta tabla:

source:     query string (?name=...)
sink malo:  innerHTML
impacto:    input no confiable se interpreta como markup
fix:        textContent para renderizar texto

Lo que practicás en este lab

Llevátelo a tu repo si querés, pero no es obligatorio: es tu aprendizaje.

  • Archivo HTML local vulnerable y versión corregida
  • Screenshot o nota mostrando que el payload queda como texto
  • Writeup con source, sink, impacto y mitigación

Reto

Armá una mini página local que lea ?name= de la URL. Primero renderizalo mal con innerHTML, después corregilo con textContent. Explicá source, sink y fix.

Resolvelo y escribí dos líneas explicando qué pasó. Con eso lo fijás.

¿Hiciste el lab?

Si querés, guardá lo que hiciste (comandos, notas, un repo) para volver después. Y si encontrás un error o querés mejorar este lab,contribuí al repo. El progreso se guarda solo en tu navegador.