saltar al contenido
volver al mapa
concepto
etapa: design
3 min de lectura

A06 Insecure Design

Una implementación perfecta de un mal diseño sigue siendo una vulnerabilidad. La seguridad hay que pedirla antes de la primera línea de código, como un requisito, y no encontrarla después como un bug.

OWASP Threat DragonMicrosoft Threat Modeling ToolSTRIDEOWASP ASVSOWASP SAMMabuse-case workshops

Qué es

Insecure design es una debilidad en cómo se concibe una funcionalidad: un control ausente, una suposición de confianza que no se sostiene o un flujo de negocio que puede abusarse tal como está escrito. Se diferencia de un bug de implementación. Un bug es código que no hace lo que dice el diseño; un diseño inseguro es código que hace exactamente lo que dice el diseño, y el problema es el diseño.

El :2025 lo mantiene como A06. La solución es más una práctica que un parche: haz threat modeling temprano, escribe casos de abuso junto a los casos de uso y reutiliza patrones de diseño seguro.

Cómo funciona el ataque

  • Un restablecimiento de contraseña que pregunta "¿cómo se llamaba tu primera mascota?" permite que cualquiera que pueda investigarte tome la cuenta.
  • Un endpoint de cupones sin límite por cliente permite que un script agote la promoción en minutos.
  • Un flujo de venta de entradas que reserva asientos sin expiración permite que un bot bloquee todo el recinto.
  • Un checkout de varios pasos que confía en el precio enviado en el último paso permite que los usuarios paguen lo que quieran.
  • Un formulario de "olvidé mi usuario" que revela si un correo está registrado permite la enumeración de cuentas.

Diseño vulnerable, en código

El código de abajo es limpio y no tiene bugs. El diseño permite que un atacante pruebe códigos promocionales sin límite y confía en un precio suministrado por el cliente.

checkout.pypython
@app.post("/api/checkout")
@login_required
def checkout():
    data = request.get_json()
    total = data["total"]                       # precio decidido por el cliente
    code = data.get("promo")
    if code and Promo.query.filter_by(code=code).first():
        total = total * 0.5                     # intentos ilimitados, reutilización ilimitada
    return charge(current_user, total)

La corrección

Diseña los controles dentro del flujo: el servidor calcula el precio a partir de datos confiables, un código promocional es de un solo uso por cuenta y los intentos tienen , y los límites son reglas de negocio escritas antes de codificar. El "enumerar códigos promocionales" produjo el requisito.

checkout.pypython
@app.post("/api/checkout")
@login_required
@rate_limit("10/minute", key=lambda: current_user.id)
def checkout():
    cart = Cart.for_user(current_user)           # fuente de verdad en el servidor
    total = cart.total()                         # los precios vienen del catálogo
    code = request.get_json().get("promo")
    if code:
        promo = Promo.redeem(code, user=current_user)   # un solo uso por usuario, atómico
        if promo is None:
            abort(400, "invalid promo")
        total = promo.apply(total)
    return charge(current_user, total)

Demuestra la corrección

Un control de diseño necesita una prueba escrita a partir del caso de abuso, no del camino feliz. Cada caso de abuso que listaste se convierte en una prueba automatizada: el cliente no puede fijar el precio, un código no puede reutilizarse y una ráfaga de intentos se limita.

test_checkout_abuse.py (pytest)python
def test_client_cannot_choose_the_price(client, alice, cart_of_100):
    r = client.post("/api/checkout", json={"total": 1}, auth=alice)
    assert charged_amount(r) == 100

def test_promo_is_single_use(client, alice, promo_half_off):
    assert client.post("/api/checkout", json={"promo": promo_half_off}, auth=alice).status_code == 200
    assert client.post("/api/checkout", json={"promo": promo_half_off}, auth=alice).status_code == 400

def test_promo_guessing_is_throttled(client, alice):
    codes = [client.post("/api/checkout", json={"promo": f"TRY{i}"}, auth=alice).status_code for i in range(30)]
    assert 429 in codes
abuse-cases.md (vive junto a las user stories)markdown
Como atacante quiero adivinar códigos promocionales para obtener descuentos que no debería.
  -> control: rate limit por cuenta y por IP, códigos largos y aleatorios, un solo uso
  -> prueba: test_promo_guessing_is_throttled

Como cliente quiero cambiar el precio en la solicitud para pagar menos.
  -> control: el precio se calcula en el servidor a partir del catálogo
  -> prueba: test_client_cannot_choose_the_price

Checklist

  • Haz threat modeling de las funcionalidades nuevas antes de construirlas: qué protegemos, quién ataca, qué los detiene ( es un buen comienzo).
  • Escribe casos de abuso junto a los casos de uso y convierte cada uno en un requisito y una prueba.
  • Reutiliza patrones probados (autenticación, rate limiting, manejo seguro de sesiones) en lugar de inventarlos.
  • Separa tenants y niveles de confianza por diseño; limita el uso de recursos por usuario.
  • Usa un estándar como para convertir "sé seguro" en requisitos verificables.
  • Revisa el modelo cuando el diseño cambie, no una vez al año.
OWASP Top 10La lista de referencia más conocida de riesgos de seguridad en aplicaciones web (A01 control de acceso roto, A02 fallas criptográficas, A03 inyección...), revisada cada pocos años por la comunidad OWASP. Es un mapa educativo de categorías de riesgo, no un checklist de herramientas ni una certificación.ver en el glosario →Rate limitingLímite de solicitudes por entidad y ventana de tiempo. La elección de la clave (IP, cuenta, token, ASN) pesa tanto como el valor del límite.ver en el glosario →Caso de abusoUna historia de usuario escrita desde el lado del atacante. Cada una produce un requisito y una prueba.ver en el glosario →STRIDEMnemónico de seis categorías de amenaza (Spoofing, Tampering, Repudiation, Information disclosure, Denial of service, Elevation of privilege) usado como checklist al recorrer un diagrama de flujo de datos.ver en el glosario →OWASP ASVSestándar de verificaciónApplication Security Verification Standard: checklist verificable, en tres niveles de rigor, para auditar una aplicación o contratar una auditoría. Donde el Top 10 enseña, el ASVS audita.ver en el glosario →

conexiones en el mapa

actualizado el 14/10/2026 · fuentes para profundizar · reportar un error

en otros dominios

Estudia antes

pon a prueba lo que entendiste

Cargando preguntas…