saltar al contenido
volver al mapa
práctica
etapa: ship
3 min de lectura

A02 Security Misconfiguration

Los valores por defecto se hacen para la comodidad, no para internet. Una bandera de debug, un bucket abierto, un error detallado o una contraseña por defecto convierten código correcto en un incidente.

TrivyCheckovScoutSuite / ProwlerMozilla ObservatorynmapOpenSCAP / CIS benchmarks

Qué es

Security misconfiguration es cualquier brecha entre cómo está configurado un sistema y cómo debería estarlo: funciones innecesarias habilitadas, cuentas por defecto sin tocar, modo debug en producción, headers de seguridad ausentes, permisos de nube permisivos o stack traces mostrados a los usuarios.

Es el A02 en el :2025 porque está en todas partes y es barato de encontrar: los atacantes escanean todo internet en busca de los mismos pocos errores.

Cómo funciona el ataque

  • Un framework dejado en modo debug expone una consola interactiva o stack traces completos con rutas de archivos y secretos.
  • Un bucket de almacenamiento, una base de datos o un panel de administración es accesible desde internet con credenciales por defecto o sin ellas.
  • El listado de directorios o un /.git, /.env o archivo de respaldo olvidado filtra código fuente y claves.
  • Los parsers XML con entidades externas habilitadas permiten que un documento manipulado lea archivos locales.
  • Un permisivo (origen comodín con credenciales) permite que cualquier sitio web llame a la API como la víctima.

Configuración vulnerable

Tres formas comunes: debug activado, CORS comodín con credenciales y un contenedor público que expone una base de datos.

app.py (Flask)python
app = Flask(__name__)
app.config["DEBUG"] = True            # depurador interactivo accesible en producción
CORS(app, origins="*", supports_credentials=True)
docker-compose.ymlyaml
services:
  db:
    image: postgres:latest
    ports:
      - "5432:5432"            # publicado en todas las interfaces
    environment:
      POSTGRES_PASSWORD: postgres
bucket.tfhcl
resource "aws_s3_bucket_public_access_block" "assets" {
  bucket                  = aws_s3_bucket.assets.id
  block_public_acls       = false
  block_public_policy     = false
}

La corrección

Haz que la configuración segura sea la predeterminada y constrúyela una vez: una imagen base endurecida, un módulo de configuración revisado y los mismos ajustes en todos los entornos, aplicados desde código. Elimina lo que no uses.

app.pypython
app = Flask(__name__)
app.config["DEBUG"] = os.environ.get("APP_ENV") == "development"
CORS(app, origins=["https://app.example.com"], supports_credentials=True)

@app.after_request
def set_headers(resp):
    resp.headers["Strict-Transport-Security"] = "max-age=31536000; includeSubDomains"
    resp.headers["X-Content-Type-Options"] = "nosniff"
    resp.headers["Content-Security-Policy"] = "default-src 'self'"
    return resp
docker-compose.ymlyaml
services:
  db:
    image: postgres:16
    expose:
      - "5432"                 # accesible solo para otros servicios de la red
    environment:
      POSTGRES_PASSWORD_FILE: /run/secrets/db_password
    secrets:
      - db_password
bucket.tfhcl
resource "aws_s3_bucket_public_access_block" "assets" {
  bucket                  = aws_s3_bucket.assets.id
  block_public_acls       = true
  block_public_policy     = true
  ignore_public_acls      = true
  restrict_public_buckets = true
}

Demuestra la corrección

La mala configuración se verifica escaneando, no leyendo código. Ejecuta un scanner de configuración en el CI contra e imágenes, y ejecuta una pequeña verificación contra la app desplegada. La prueba rompe el build cuando un valor seguro por defecto regresa a su estado inseguro.

ci-checks.shbash
# 1. código de infraestructura: fallar con recursos mal configurados
checkov -d infra/ --quiet --compact

# 2. imagen de contenedor: fallar con hallazgos HIGH/CRITICAL
trivy image --exit-code 1 --severity HIGH,CRITICAL registry.example.com/app:$GIT_SHA

# 3. app desplegada: los headers requeridos deben estar presentes
curl -sI https://staging.example.com | grep -qi '^strict-transport-security:' || exit 1
curl -sI https://staging.example.com | grep -qi '^content-security-policy:' || exit 1
test_config.py (pytest)python
def test_debug_is_off_in_production(monkeypatch):
    monkeypatch.setenv("APP_ENV", "production")
    assert create_app().config["DEBUG"] is False

def test_cors_does_not_allow_any_origin(client):
    resp = client.options("/api/me", headers={"Origin": "https://evil.example"})
    assert resp.headers.get("Access-Control-Allow-Origin") != "*"

Checklist

  • Un proceso de hardening repetible y automatizado para cada entorno; nada de servidores ajustados a mano.
  • Elimina funciones sin uso, apps de ejemplo, cuentas por defecto y puertos abiertos.
  • Envía los headers de seguridad que apliquen (HSTS, CSP, X-Content-Type-Options, protección contra frames).
  • Muestra errores genéricos a los usuarios; envía los detalles a los logs, no a la respuesta.
  • Revisa los permisos de nube y la exposición del almacenamiento de forma continua, no una sola vez.
  • Trata la configuración como código: revisada, versionada, escaneada.
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 →CORSintercambio de recursos entre orígenesUn mecanismo del navegador que permite a un servidor indicar qué otros orígenes pueden leer sus respuestas. Un origen comodín combinado con credenciales es una mala configuración.ver en el glosario →IaCinfraestructura como códigoDescribir la infraestructura en archivos versionados (Terraform, Ansible). Aporta revisión, historial y pruebas a la configuración, pero replica errores a escala si no se escanea.ver en el glosario →

conexiones en el mapa

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

en otros dominios

pon a prueba lo que entendiste

Cargando preguntas…