Como mitigar un ataque XSS

Introducción Mitigación XSS

Introducción

El ataque XSS (Cross-Site Scripting) es una vulnerabilidad que permite a un atacante inyectar código JavaScript a un sitio web. Este código se le hace llegar al usuario final, y se ejecuta en el navegador de este, lo que permite al atacante robar información, secuestrar sesiones, realizar acciones en la sesión del usuario sin su consentimiento o redirigir a sitios maliciosos.

Explotación

El ataque XSS se puede llevar a cabo de varias maneras, mientras se tenga como input un campo que se muestre en el sitio web. Algunos ejemplos de esto son:

  • Formularios (como campos de texto, selectores, etc.)
  • Headers (como Referer, User-Agent o Cookie)
  • JSON (en APIs)

Código vulnerable

A continuación se muestra un ejemplo de código vulnerable a XSS:

from flask import Flask, request, render_template_string
 
app = Flask(__name__)
 
 
@app.route("/", methods=["GET"])
def index():
    name = request.args.get("name", "Invitado")
    # Vulnerable a XSS, el valor de name se inyecta directamente en la respuesta HTML
    return render_template_string("<h1>Hola, {}!</h1>".format(name))
 
 
if __name__ == "__main__":
    app.run()

El comportamiento esperado de este código es mostrar un saludo al usuario con el nombre que este haya ingresado como se muestra en la siguiente imagen:

Código Vulnerable

Sin embargo, si un atacante ingresa el siguiente texto en el campo name: <script>alert("XSS")</script>, el código vulnerable mostrará un mensaje emergente en el navegador del usuario, como se muestra en la siguiente imagen:

Código Vulnerable

Mitigación

Para mitigar un ataque XSS, se pueden seguir las siguientes recomendaciones:

  • Validación de inputs: Validar que los inputs no contengan caracteres especiales que puedan ser interpretados como código. Teniendo una lista blanca de caracteres permitidos.
  • Escapado de caracteres: Escapar los caracteres especiales antes de mostrarlos en el sitio web. Esto evita que el navegador los interprete como código. Es recomendado usar las herramientas del framework que se esté utilizando.
  • Sanitización de inputs: Limpiar los inputs de caracteres especiales antes de mostrarlos en el sitio web.
  • Headers de seguridad: Configurar los headers de seguridad en el servidor para prevenir ataques XSS.
  • Frameworks seguros: Utilizar frameworks seguros que mitiguen automáticamente ataques XSS.

La mitigación depende del contexto del desarrollo de la pieza de software en donde se debe elegir las mejores opciones para abarcar la mayor seguridad posible a la hora de realizar codigo seguro.

Codigo seguro

A continuación se muestra un ejemplo de código seguro a XSS:

from flask import Flask, request, render_template_string
 
app = Flask(__name__)
 
 
@app.route("/", methods=["GET"])
def index():
    name = request.args.get("name", "Invitado")
    # Seguro contra XSS, el valor de name se escapa antes de ser inyectado en la respuesta HTML
    return render_template_string("<h1>Hola, {{ name }}!</h1>", name=name)
 
 
if __name__ == "__main__":
    app.run()

El comportamiento esperado de este código es mostrar un saludo al usuario con el nombre que este haya ingresado, sin importar si este contiene caracteres especiales, como se muestra en la siguiente imagen:

Código Seguto

Otros ejemplos

  • Validación de inputs:
import re
name = request.args.get("name", "Invitado")
name = re.sub('[^A-Za-z ]+', '', name)
  • Escapado de caracteres:
from flask import escape
 
name = request.args.get("name", "Invitado")
return "<h1>Hola, {}!</h1>".format(escape(name))
  • Sanitización de inputs:
import bleach
 
name = request.args.get("name", "Invitado")
return "<h1>Hola, {}!</h1>".format(bleach.clean(name))
  • Headers de seguridad: Establecer Políticas de Seguridad de Contenido (CSP). Puedes hacerlo agregando una cabecera HTTP Content-Security-Policy. Flask puede configurar esto para todas las respuestas usando el decorador after_request.
@app.after_request
def set_csp(response):
    response.headers['Content-Security-Policy'] = "default-src 'self'"
    return response
  • Frameworks seguros: Uso de Jinja2 para renderizar plantillas (recomendado)
# En lugar de render_template_string, usa:
return render_template("index.html", name=name)

index.html:

<h1>Hola, {{ name }}!</h1>

Conclusión

Si bien el Cross-Site Scripting es una vulnerabilidad antigua, su explotación es común en el ciberespacio. Es importante tener en cuenta las recomiendaciones para mitigarla, ya que puede ser explotada de manera sencilla y causar daños significativos a los usuarios y a la empresa.

Referencias

-Cross-Site Scripting (XSS) - xss payloads collect
-Cross Site Scripting (XSS) - OWASP
-What is cross-site scripting (XSS)?