🛡️ Taller de Seguridad III

Informe de mejoras en servidores web · TLS 1.3 · HTTP/3 · HSTS · CORS · CSP avanzado · Hardening de cabeceras · Cookies seguras · Security.txt

📊 Información del proyecto

📌 Descargo

En este Taller de Seguridad (el tercero en su tipo) se han aplicado las directivas de seguridad generales a nivel de servidor.
El objetivo es aumentar y mejorar la seguridad general de todas las aplicaciones contenidas en los sitios IIS, de cada servidor web.
Así que lo que se ha buscado son directivas y configuraciones que brindar un mayor blindado de todo el servidor.
Sin embargo, se debe indicar claramente que la mayoría de las revisiones de seguridad se hacen contra el SSO-CFIA, es decir, se aplican escaneos y validaciones a ese sistema puntual, pues es la puerta de entrada de los sistemas críticos del CFIA. Así que se le da prioridad en su blindado de seguridad.
Esto quiere decir que, en un análisis puntual de otro sistema, se pueden tener resultados diferentes a la hora de revisar configuraciones y validaciones de seguridad. En esos casos, todas las vulnerabilidades deben ser documentadas, analizadas y atendidas por separado (para cada sistema).

Feb - Abr
📅 Período de trabajo
13
✅ Mejoras implementadas
125
⏱️ Horas invertidas
Pendiente
⚙️ Estado actual
Pase a Producción

📈 Evolución de la calificación de seguridad

🔴 Producción

D+
📄 Descargar informe (PDF)
➡️
📈 Esto implica un avance de 5 posiciones en la escala de calificación (de D+ a B), reflejando una mejora sustancial en la postura de seguridad.

📊 Progreso por áreas clave

TLS 1.399%
HTTP/3 (QUIC)99%
CORS / Orígenes75%
Seguridad en cookies99%
CSP (Content Security Policy)85%
Security.txt99%
F
0
E
1
D-
2
D+
3
C-
4
C
5
C+
6
B-
7
B
8
B+
9
A-
10
A
11
A+
12

La calificación mejoró de D+ (posición 3) a B (posición 8), un avance de 5 posiciones.

🎯 Próximos pasos

  • Completar la habilitación de HTTP/3 (QUIC) resolviendo el bloqueo de firewall.
  • Eliminar 'unsafe-inline' y 'unsafe-eval' de la CSP mediante nonces + strict-dynamic.
  • Restringir img-src y style-src a dominios concretos.
  • Aplicar la configuración de CORS basada en la lista de orígenes recopilada (Taller Seguridad IV).
  • Habilitar security.txt en todos los dominios de producción.

🔐 TLS 1.3

📌 Importancia

TLS 1.3 es la versión más reciente del protocolo de cifrado para comunicaciones web. Elimina algoritmos obsoletos (RC4, SHA-1, CBC) y reduce la latencia de handshake de 2 RTT a 1 RTT (0-RTT para sesiones reanudadas). Ofrece forward secrecy obligatorio, protegiendo comunicaciones pasadas incluso si la clave privada se compromete. Su implementación es crítica para obtener calificación A+ en Mozilla Observatory y cumplir con estándares como PCI DSS 4.0. Además, permite el uso de HTTP/3 sobre QUIC, que requiere TLS 1.3 como base.

⚙️ Implementación

Llave en registro de Windows:

Computer\HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\TLS 1.3\Server
Enabled = 1 o fffff

Nota: Ya está habilitado en los servidores web. No se requiere ningún paso adicional.

Importante: para que se use al 100% el TLS 1.3, se debe tener activo y funcionando HTTP/3. Si aparece TLS 1.3 pero el protocolo sigue diciendo h2 (HTTP/2), significa que usas cifrado moderno sobre transporte antiguo (TCP). Para HTTP/3 real, el transporte debe decir QUIC. Resumen: si ves QUIC, ya estás en el "futuro". Si ves TLS 1.3 con h2, el cifrado es correcto pero HTTP/3 sigue fallando por bloqueo en puerto 443 UDP o falta de configuración en el registro.

⏳ Pendiente

Falta habilitar completamente HTTP/3 (ver sección siguiente).

🚀 HTTP/3 (QUIC)

📌 Importancia

HTTP/3 no es una simple actualización; rediseña el transporte usando QUIC (UDP). Ventajas clave: eliminación del head-of-line blocking (una pérdida en TCP detiene todos los flujos), handshake 0-RTT para usuarios recurrentes, migración de conexión sin interrupción al cambiar de red (Wi-Fi ↔ móvil), cifrado obligatorio con TLS 1.3, y mejor rendimiento en redes con alta pérdida de paquetes (entornos móviles, satelitales). La combinación TLS 1.3 + HTTP/3 proporciona la mejor seguridad y rendimiento disponible.

⚙️ Implementación

Pasos para habilitar HTTP/3 en IIS:

  1. Requisito previo: Asegurar el uso de HTTPS con un certificado SSL válido en el puerto 443.
  2. Habilitar en el Registro: Ejecute regedit, navegue a HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\HTTP\Parameters, cree un nuevo valor DWORD (32-bit) llamado EnableHttp3 y establézcalo en 1.
  3. Reinicie el servicio HTTP.sys (PowerShell):
    # Detiene el servicio HTTP y todos sus dependientes (incluyendo IIS) net stop http /y
    # Inicia el servicio HTTP nuevamente
    net start http
    # Inicia el servicio de activación de procesos de Windows (necesario para IIS)
    net start w3svc
    # activar cipher
    Enable-TlsCipherSuite -Name TLS_CHACHA20_POLY1305_SHA256 -Position 0
  4. Reiniciar el servidor.
  5. Configurar el Encabezado de Respuesta (Alt-Svc): Abra el Administrador de IIS, seleccione su sitio web, abra Encabezados de respuesta HTTP, añada uno nuevo: Nombre: alt-svc, Valor: h3=":443"; ma=86400; persist=1. Reinicie IIS.
  6. Activar UDP en 443 en firewall:
    • Verificar regla en Firewall de Windows:
      Get-NetFirewallRule | where { $_.Enabled -eq "True" -and $_.Direction -eq "Inbound" } | Get-NetFirewallPortFilter | where { $_.Protocol -eq "UDP" -and $_.LocalPort -eq "443" }
      Si no devuelve nada: no hay regla activa. Si aparece información: la regla existe y está habilitada.
    • Verificar si el servidor está "escuchando" (Listening):
      netstat -ano | findstr ":443"
      Busque líneas que digan UDP. Si solo ves TCP, el soporte de HTTP/3 no se ha activado correctamente o el servidor no se ha reiniciado.
    • Crear la regla (si no existe):
      New-NetFirewallRule -DisplayName "IIS HTTP3 (UDP-443)" -Direction Inbound -Action Allow -Protocol UDP -LocalPort 443
    • Prueba externa (la más fiable): Use herramientas como HTTP/3 Check de Geekflare o el escáner de puertos de DNSChecker seleccionando UDP. A diferencia de TCP, UDP es un protocolo "sin conexión", las pruebas simples de terminal suelen fallar o dar falsos negativos.
  7. Verificación: Abra su sitio en Edge/Chrome, F12 → Red → agregue columna "Protocolo" y asegúrese de que aparezca h3. Si aparece TLS 1.3 pero el protocolo sigue diciendo h2 (HTTP/2), el cifrado es correcto pero HTTP/3 falla por bloqueo UDP o falta de configuración. Nota: La primera solicitud puede usar HTTP/2, cambiando a HTTP/3 tras detectar alt-svc. Importante: revisar primero en el servidor mismo; si funciona, probar desde fuera; si no funciona desde fuera, 100% tema de router/firewall.

⏳ Pendiente

Está fallando el h3 por un tema de proxy o firewall. El equipo de Infraestructura va a revisar.

🛡️ HSTS (Strict-Transport-Security)

📌 Importancia

Nota: no se puede aplicar masivo, pues tenemos APIs que son consumidas desde fuera del CFIA. Las APIs de seguridad, los WCF que se consumen desde municipalidades y otras instituciones deben quedar abiertos. Respuesta: como la segregación requiere documentación clara sobre quién consume, no podemos cerrar el acceso. Se aplicará al sistema del SSO.

HSTS fuerza a los navegadores a conectar únicamente mediante HTTPS durante el tiempo especificado (max-age), evitando ataques de downgrade (SSL stripping) y garantizando que las cookies con bandera Secure se transmitan siempre cifradas. Es un requisito para obtener puntuaciones A+ en Mozilla Observatory y para ser incluido en la lista de precarga (preload).

⚙️ Implementación (mediante URL Rewrite en IIS)

  1. Antes de crear la regla, debes permitir que el módulo modifique el encabezado de respuesta:
    • Abre el Administrador de IIS y selecciona tu sitio en el panel izquierdo.
    • En la vista de características, haz doble clic en URL Rewrite.
    • En el panel de Actions (derecha), haz clic en View Server Variables....
    • Haz clic en Add... y escribe exactamente: RESPONSE_Strict_Transport_Security.
    • Haz clic en Back to Rules.
  2. Crear la Regla de Salida (Outbound Rule):
    • En el panel de Actions, haz clic en Add Rule(s)....
    • En la sección Outbound rules, selecciona Blank rule y pulsa OK.
    • Configura la regla con los siguientes valores:
      - Name: Habilita HSTS
      - Matching Scope: Cambia a Server Variable.
      - Variable name: Selecciona RESPONSE_Strict_Transport_Security.
      - Variable value: Selecciona Matches the pattern y usa Regular Expressions.
      - Pattern: .* (coincide con cualquier valor actual del encabezado).
  3. Configurar la Condición (filtro por HTTPS):
    • Expande la sección Conditions y haz clic en Add....
    • Condition input: Escribe {HTTPS}.
    • Check if input string: Selecciona Matches the pattern.
    • Pattern: on (solo cuando la petición original es HTTPS).
    • Haz clic en OK.
  4. Definir la Acción:
    • En la sección Action, asegúrate de que esté en Rewrite.
    • Value: Escribe max-age=31536000; includeSubDomains; preload.
    • Haz clic en Apply en el panel de la derecha para guardar los cambios.
  5. Verificación: Una vez aplicada, puedes probar desde la consola del navegador en un subdominio. La cabecera Strict-Transport-Security debería aparecer en las respuestas HTTPS. La configuración resultante en web.config debe ser:
<outboundRules>
<rule name="Habilita HSTS" enabled="true">
<match serverVariable="RESPONSE_Strict_Transport_Security" pattern=".*" />
<conditions>
<add input="{HTTPS}" pattern="on" ignoreCase="true" />
</conditions>
<action type="Rewrite" value="max-age=31536000; includeSubDomains; preload" />
</rule>
</outboundRules>

Validación externa: https://cors-test.codehappy.dev/

Prueba desde consola del navegador:

fetch('https://test-apc.cfia.or.cr')
.then(response => {
console.log('¿CORS exitoso?:', response.ok);
console.log('Headers de respuesta:', [...response.headers]);
})
.catch(error => console.error('Error de CORS detectado:', error));

Interpretación: Si ves los datos o un objeto Response, el servidor permite el origen actual. Si ves un error, el encabezado Access-Control-Allow-Origin falta o no coincide. Para verificar HSTS específicamente, busca la cabecera strict-transport-security en la pestaña Network.

⏳ Pendiente

Sólo su aplicación en Producción.

🌐 Orígenes CORS y logging (Access-Control-Allow-Origin)

📌 Importancia

Access-Control-Allow-Origin es indispensable para proveer seguridad a los sistemas y dominios web. Sin embargo, en este momento no se puede aplicar masivo, pues tenemos APIs que son consumidas desde fuera del CFIA. Las APIs de seguridad, los WCF que se consumen desde municipalidades y otras instituciones deben quedar abiertos.

Estrategia: Como la segregación requiere documentación clara sobre quién consume, no podemos cerrar el acceso. Lo que se debe realizar primero es la generación de la lista de orígenes. Con esa lista se podrá definir el CORS con las condiciones de consumo que permita los dominios válidos. Nota: esto (logging y CORS) no se afecta por el consumo de APIs desde aplicaciones móviles o de escritorio.

⚙️ Implementación (configuración de logging de orígenes)

  1. Activar y configurar el registro W3C:
    • Abre el Administrador de IIS y selecciona tu sitio web en el panel de conexiones.
    • Haz doble clic en el icono "Logging".
    • Asegúrate de que en "Format:" esté seleccionado W3C.
  2. Añadir el campo personalizado:
    • Dentro de la misma ventana, haz clic en el botón "Select Fields..." (o "Choose Fields").
    • En la nueva ventana, desplázate hasta la sección "Custom Fields" y haz clic en "Add Field...".
    • En el cuadro de diálogo, completa la información:
      - Field name: X-Origin (sin espacios).
      - Source type: Request Header.
      - Source: Origin.
      Haz clic en OK para guardar el campo.
  3. Finalizar la configuración:
    • En la ventana "W3C Logging Fields", asegúrate de que tu nuevo campo X-Origin esté marcado y haz clic en OK.
    • En la ventana principal de "Logging", haz clic en "Apply" en el panel de acciones.
  4. Localizar los logs:
    • Los logs se seguirán guardando en tu ruta habitual de logs de IIS (por ejemplo, C:\inetpub\logs\LogFiles\W3SVC1\).
    • Para identificar los archivos que contienen campos personalizados, el nombre incluirá el sufijo _x, como exYYMMDD_x.log.
  5. Análisis de los Logs: Cómo Obtener la Lista de Dominios Únicos

    Una vez que los logs se estén generando con el nuevo campo, puedes extraer la lista de orígenes únicos fácilmente con PowerShell. A continuación se muestra el script de ejemplo (recursivo, exporta a D:\Logs\CORS\origenes_cors.txt):

    # Ruta base donde se encuentran las carpetas de logs de IIS (puede contener subcarpetas W3SVC*)
    $logBasePath = "C:\inetpub\logs\LogFiles\"
    # Buscar recursivamente todos los archivos que terminan en _x.log
    $logFiles = Get-ChildItem -Path $logBasePath -Recurse -Filter "*_x.log" -ErrorAction SilentlyContinue
    if ($logFiles.Count -eq 0) {
    Write-Host "No se encontraron archivos de log con campos personalizados (_x.log) en la ruta especificada." -ForegroundColor Yellow
    exit
    }
    $origenes = @()
    foreach ($file in $logFiles) {
    Write-Host "Procesando: $($file.FullName)" -ForegroundColor Cyan
    $lines = Get-Content $file.FullName -ErrorAction SilentlyContinue
    # Buscar la línea que contiene los encabezados (#Fields)
    $headersLine = $lines | Where-Object { $_ -match '^#Fields:' } | Select-Object -First 1
    if (-not $headersLine) {
    Write-Host " No se encontró línea #Fields en este archivo." -ForegroundColor Yellow
    continue
    }
    # Extraer los nombres de los campos
    $fields = $headersLine -replace '#Fields: ' -split ' '

    # Buscar el índice del campo personalizado (por ejemplo, "X-Origin")
    $fieldIndex = -1
    for ($i = 0; $i -lt $fields.Count; $i++) {
    if ($fields[$i] -eq "X-Origin") {
    $fieldIndex = $i
    break
    }
    }

    if ($fieldIndex -eq -1) {
    Write-Host " El campo 'X-Origin' no se encuentra en los encabezados de este archivo." -ForegroundColor Yellow
    continue
    }

    # Procesar las líneas de datos (las que no empiezan con '#')
    foreach ($line in $lines) {
    if ($line -match '^#' -or $line.Trim() -eq "") { continue }
    $values = $line -split ' '
    if ($values.Count -gt $fieldIndex) {
    $origin = $values[$fieldIndex]
    if ($origin -and $origin -ne '-') {
    $origenes += $origin
    }
    }
    }
    }

    # Eliminar duplicados y mostrar resultados
    $origenesUnicos = $origenes | Sort-Object -Unique

    Write-Host "`n=== ORÍGENES CORS ÚNICOS DETECTADOS ===" -ForegroundColor Green
    $origenesUnicos | ForEach-Object { Write-Host $_ }

    # Crear la carpeta de destino si no existe
    $outputFolder = "D:\Logs\CORS"
    if (-not (Test-Path $outputFolder)) {
    New-Item -ItemType Directory -Path $outputFolder -Force | Out-Null
    }

    $outputFile = Join-Path -Path $outputFolder -ChildPath "origenes_cors.txt"
    $origenesUnicos | Out-File -FilePath $outputFile
    Write-Host "`nLista exportada a: $outputFile" -ForegroundColor Green

    Al ejecutar este análisis, obtendrás una lista depurada y sin duplicados de todos los dominios que han estado interactuando con tu API a través de solicitudes web (como navegadores), información clave para construir tu lista blanca de CORS.

⏳ Pendiente

Una vez se tenga una lista de orígenes de, al menos, 1 mes se aplicará la configuración de CORS. Esta configuración nueva se aplicará en el Taller Seguridad IV.

🍪 Seguridad en cookies (Secure, HttpOnly, SameSite)

📌 Importancia

Dar seguridad a las cookies (se debe hacer por sitio). Nota: Ya aplicado al SSO. El resto de sistemas requieren una revisión puntual según su tecnología. Las cookies sin Secure pueden ser transmitidas por HTTP (MITM), sin HttpOnly son accesibles desde JavaScript (XSS), y sin SameSite son vulnerables a CSRF.

⚙️ Implementación

Para sistemas con web.config (ASP.NET Framework):

<system.web>
<!-- 1. Forzar cookies solo por HTTPS (Secure) y ocultarlas de JavaScript (HttpOnly) -->
<httpCookies httpOnlyCookies="true" requireSSL="true" lockItem="true" />

<!-- 2. Para el Session State -->
<sessionState cookieSameSite="Lax" />
</system.web>

Para Core: debe configurar en appsettings.json y consumir tal configuración en Program.cs (CookiePolicyOptions con SecurePolicy.Always, HttpOnly.Always, SameSiteMode.Lax).

⏳ Pendiente

Sólo su aplicación en Producción.

📜 Mejoras CSP (Content Security Policy)

📌 Importancia

La CSP es la defensa principal contra XSS e inyección de datos. La política de Producción contiene comodines peligrosos (*.googleapis.com, *.google.com, *.gstatic.com, *.zdassets.com), 'unsafe-inline' y 'unsafe-eval', lo que permite ataques JSONP y ejecución de scripts maliciosos. La nueva política elimina comodines externos, fuerza HTTPS, añade reportes y base-uri, aunque aún mantiene unsafe-inline (pendiente migración a nonces).

⚙️ Implementación

0. Uso de Content-Security-Policy-Report-Only
Con este encabezado se pueden agregar modificaciones al CSP para que se notifiquen violaciones al mismo. Es sólo informativo; una vez validado que es seguro y sin afectación en sistemas, se pasa al CSP oficial.
Evaluador utilizado: https://csp-evaluator.withgoogle.com/

Pasos para crear el servicio de reporte:

  • Publique el servicio de reporte: https://sso.cfia.or.cr/csp-receiver/ReceiveCspReport.ashx (ruta física D:\IIS\SSO\Publico\Seguro\csp-receiver). Prueba simple: curl -X POST https://sso.cfia.or.cr/csp-receiver/ReceiveCspReport.ashx -d "{\"test\":\"data\"}"
  • Crear las cabeceras:
    Reporting-Endpoints: csp-endpoint="https://sso.cfia.or.cr/csp-receiver/ReceiveCspReport.ashx"
    Content-Security-Policy-Report-Only: report-uri https://sso.cfia.or.cr/csp-receiver/ReceiveCspReport.ashx; report-to csp-endpoint;
  • En Web.config del sitio de SSO (no de la aplicación) se debe incluir antes de system.webServer:
    <modules>
    <remove name="WebDAVModule" />
    </modules>

1. Actualice la CSP: Reemplazar el contenido de la CSP_Produccion (Content-Security-Policy) con el CSP_Nuevo (ver políticas completas al final de esta sección).

Reinicie el IIS (iisreset) para asegurar que se refresque.


2. Cambiar conexión a 127.0.0.1 → localhost: modificar Helper.js, bootstrap/Gruntfile.js y el CSP para sustituir 127.0.0.1 por localhost.


3. x-aspnet-version visible: Revela la versión de ASP.NET (útil para atacantes). Solución: en web.config agregar <httpRuntime enableVersionHeader="false" />. Quite la URL_Rewrite asociada (desactívela).


4. x-powered-by: CFIA personalizado pero aún expone tecnología. Solución: Eliminar encabezado y URL_Rewrite.


5. Permissions-Policy: Nombre: Permissions-Policy, Valor: geolocation=(), microphone=(), camera=self, payment=(), usb=().
Importante: 'self' se utiliza para permitir el acceso desde el mismo dominio. Como Eventos, que necesita acceso a la cámara en su dominio.


6. X-Frame-Options: Eliminarlo para dejar que el CSP Frame-Ancestors haga el trabajo.




📊 Comparativa directa: CSP_Produccion vs CSP_Nuevo

Mejoras directiva por directiva y por qué la nueva política es más segura:

DirectivaValor en CSP_Produccion (vulnerable)Valor en CSP_Nuevo (mejorado)Mejora / Razón técnica
default-src 'none' 'none' Igual (buena base).
script-src *.cfia.or.cr *.zdassets.com *.zendesk.com *.zopim.com *.googleapis.com *.google.com *.gstatic.com ... 'unsafe-inline' 'unsafe-eval' blob:
Comodines externos peligrosos (JSONP), unsafe-inline/eval.
'report-sample' https://api.smooch.io/ https://unpkg.com/ https://*.cfia.or.cr ... URLs exactas para Google, reCAPTCHA, Zendesk, etc. 'unsafe-eval' 'unsafe-inline' blob: (persiste unsafe-inline) Se eliminan comodines de terceros (Google, Zendesk, CDNs). Se mitiga el riesgo de JSONP (scripts maliciosos desde subdominios confiables). Se añade 'report-sample' para depuración. Aún pendiente eliminar unsafe-inline mediante nonces.
connect-src http://*.cfia.or.cr (HTTP inseguro), wss://127.0.0.1:31337, *.zopim.com, *.zdassets.com, *.zendesk.com (comodines) https://*.cfia.or.cr, wss://localhost:31337, https://ekr.zdassets.com/, https://*.zendesk.com, wss://api.smooch.io/, https://*.placetopay.com (solo HTTPS y dominios específicos) Elimina HTTP (fuerza HTTPS) y reduce comodines. El cambio de 127.0.0.1 a localhost mitiga ataques de DNS rebinding. Se restringe a dominios concretos, disminuyendo superficie de ataque.
font-src * *.cloudfront.net *.alignetsac.com *.verifika.com data: (comodín universal) https: data: Elimina el comodín universal *. Solo permite fuentes HTTPS, reduciendo riesgo de inyección de recursos maliciosos.
base-uri No especificado\n 'self' Previene inyección de etiqueta <base>, impidiendo que atacantes redirijan scripts o recursos a orígenes maliciosos.
report-uri / report-to No presente\n Endpoint propio https://sso.cfia.or.cr/csp-receiver/ReceiveCspReport.ashx y cabeceras Reporting-Endpoints Permite monitorizar violaciones reales sin bloquear a los usuarios (modo Report-Only), facilitando la corrección iterativa de la política.
style-src / img-src * 'unsafe-inline' y * data: blob: Mismos valores (aún permisivos) 🔴 Pendiente endurecimiento. Se debe restringir a dominios concretos y eliminar unsafe-inline mediante nonces o hashes.

⚠️ Vulnerabilidades existentes (aún presentes en CSP_Nuevo)

🔴 Crítica: Uso de 'unsafe-inline' en script-src y style-src – Permite la ejecución de scripts y estilos inline arbitrarios, facilitando ataques XSS. Importancia: Es la principal puerta de entrada para inyección de código malicioso. Se debe migrar a nonces + strict-dynamic.

🟠 Alta: img-src * data: blob: – Permite cargar imágenes desde cualquier origen, lo que puede ser usado para píxeles de rastreo maliciosos o exfiltración de datos. Importancia: Riesgo de fuga de información.

🟡 Media: Comodines internos (https://*.cfia.or.cr, https://*.jquery.com, https://*.alignetsac.com, etc.) – Aunque reducidos, siguen siendo comodines. Si algún subdominio es comprometido o se expone un endpoint JSONP, podría ejecutarse código malicioso. Importancia: Menor que los comodines externos, pero aún riesgoso.

🟡 Media: Uso de 'unsafe-eval' – Permite el uso de eval(), setTimeout(string), etc., facilitando la ejecución dinámica de código inyectado. Importancia: Debe eliminarse en favor de código seguro.

🟢 Baja (actual): blob: y data: en script-src y otras directivas – Pueden ser abusados en combinación con otras vulnerabilidades. Importancia: Riesgo limitado si no existen otros vectores, pero se recomienda eliminarlos.

📄 CSP completos (Producción y Nuevo)

CSP_Produccion (original, vulnerable):

default-src 'none'; script-src *.cfia.or.cr *.zdassets.com *.zendesk.com *.zopim.com *.googleapis.com *.google.com *.gstatic.com www.googletagmanager.com www.google-analytics.com *.jquery.com *.alignetsac.com *.verifika.com cdn.datatables.net cdn.jsdelivr.net cdnjs.cloudflare.com *.cloudfront.net 'unsafe-inline' 'unsafe-eval' blob:; media-src *.zdassets.com blob:; object-src 'none'; img-src * data: blob:; style-src * 'unsafe-inline'; manifest-src *.cfia.or.cr; font-src * *.cloudfront.net *.alignetsac.com *.verifika.com data:; connect-src http://*.cfia.or.cr https://*.cfia.or.cr cfia.aurainteractiva.com *.zopim.com *.zdassets.com *.zendesk.com *.hacienda.go.cr www.google-analytics.com *.googleapis.com *.google.com stats.g.doubleclick.net *.alignetsac.com *.verifika.com ka-f.fontawesome.com wss://widget-mediator.zopim.com wss://127.0.0.1:31337 https://127.0.0.1:31337 wss://*.cfia.or.cr; frame-ancestors *.cfia.or.cr *.google.com *.alignetsac.com *.verifika.com; frame-src *.cfia.or.cr *.google.com *.alignetsac.com *.verifika.com;

CSP_Nuevo (mejorado, aplicado):

default-src 'none'; script-src 'report-sample' https://api.smooch.io/ https://unpkg.com/ https://*.cfia.or.cr https://*.jquery.com https://*.alignetsac.com https://*.verifika.com https://cdn.datatables.net/ 'unsafe-eval' 'unsafe-inline' blob: https://www.google-analytics.com/analytics.js https://www.google.com/recaptcha/api.js https://www.gstatic.com/recaptcha/releases/ https://static.zdassets.com/web_widget/classic/latest/ https://www.googletagmanager.com/ https://static.zdassets.com/ https://analytics.google.com/ https://www.google-analytics.com/ https://*.cloudfront.net https://cdn.jsdelivr.net/ https://cdnjs.cloudflare.com/; media-src https://*.zdassets.com blob:; object-src 'none'; img-src * data: blob:; style-src * 'unsafe-inline' 'report-sample'; manifest-src https://*.cfia.or.cr; font-src https: data:; connect-src https://*.cfia.or.cr https://cfia.aurainteractiva.com/ https://*.hacienda.go.cr https://analytics.google.com https://www.google-analytics.com/ https://*.googleapis.com https://*.google.com https://stats.g.doubleclick.net/ https://*.alignetsac.com https://*.verifika.com https://ka-f.fontawesome.com/ wss://widget-mediator.zopim.com wss://localhost:31337 https://localhost:31337 wss://*.cfia.or.cr wss://api.smooch.io/ https://ekr.zdassets.com/ https://*.zendesk.com https://*.placetopay.com; frame-ancestors https://*.cfia.or.cr https://*.google.com https://*.alignetsac.com https://*.verifika.com; frame-src https://*.cfia.or.cr https://*.google.com https://*.alignetsac.com https://*.verifika.com; base-uri 'self'; report-uri https://sso.cfia.or.cr/csp-receiver/ReceiveCspReport.ashx; report-to csp-endpoint;

⏳ Pendiente

Vulnerabilidades aún existentes (ver tabla y lista arriba). Su aplicación en Producción.

📁 Mejoras SSO

Estas modificaciones son específicas del SSO-CFIA, por lo que no se verán reflejadas en otros sistemas. Sin embargo, es posible aplicarlas a otros sistemas, especialmente, los que utilizan un archivo web.config para contener su configuración.

📌 Mejoras en código y configuración

  • Eliminación de JavaScript vulnerable: Se removieron librerías y fragmentos de código con vulnerabilidades conocidas (por ejemplo, versiones obsoletas de jQuery, Bootstrap JS con fallos de XSS). Se actualizaron a versiones parcheadas o se reemplazaron por implementaciones nativas.
  • Eliminación de CSS vulnerable: Se eliminaron hojas de estilo inline inseguras y se migraron a archivos externos, evitando la inyección de estilos maliciosos mediante CSP.
  • Migración de sentencias JavaScript inline a archivos externos: Todo el código JavaScript que estaba embebido en páginas .aspx (eventos inline, bloques <script> sin nonce) se trasladó a archivos .js separados, permitiendo aplicar políticas CSP estrictas sin unsafe-inline.
  • Control de eventos HTML mediante addEventListener: Los manejadores de eventos (onclick, onload, etc.) se reemplazaron por listeners en JavaScript externo, eliminando la necesidad de unsafe-inline y mejorando la mantenibilidad.
  • Agregado de meta robots: Se incluyó la etiqueta <meta name="robots" content="noindex, nofollow"> en las páginas del SSO para evitar indexación no deseada por motores de búsqueda (aunque no es una medida de seguridad directa, reduce la exposición de información sensible).
  • Mejoras en web.config (seguridad a nivel de aplicación):
    • <pages validateRequest="true" controlRenderingCompatibilityVersion="4.0"/>: Habilita la validación automática de solicitudes para prevenir ataques de inyección (XSS). La versión 4.0 asegura compatibilidad con el motor de renderizado moderno.
    • <httpRuntime encoderType="System.Web.Security.AntiXss.AntiXssEncoder, System.Web, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />: Configura el encoder de salida para usar la librería AntiXSS de Microsoft, que codifica caracteres peligrosos de forma más agresiva que el encoder por defecto, mitigando XSS en la generación de HTML.
    • <httpCookies httpOnlyCookies="true" requireSSL="true" lockItem="true" />: Fuerza que todas las cookies de sesión sean accesibles solo por HTTP (no por JavaScript) y solo se transmitan por HTTPS (bandera Secure), evitando robo de sesión. lockItem impide que configuraciones inferiores lo anulen.
    • <sessionState cookieSameSite="Lax" />: Establece la política SameSite para la cookie de sesión en "Lax", protegiendo contra ataques CSRF al permitir el envío de la cookie solo en navegaciones seguras (enlaces desde el mismo sitio).
    • Configuración completa de httpRuntime: Se ha unificado y ampliado la línea httpRuntime para incluir:
      <httpRuntime requestValidationMode="4.5" enableVersionHeader="false" maxRequestLength="10485760" encoderType="System.Web.Security.AntiXss.AntiXssEncoder, System.Web, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
      - requestValidationMode="4.5": Activa la validación de solicitudes más estricta contra XSS (compatible con .NET 4.5+).
      - enableVersionHeader="false": Elimina la cabecera X-AspNet-Version en las respuestas, dificultando el fingerprinting del servidor.
      - maxRequestLength="10485760": Limita el tamaño máximo de las solicitudes HTTP a 10 MB, mitigando ataques de denegación de servicio (DoS) por envío masivo de datos.
      - encoderType: (ya explicado) codificación segura contra XSS.
    • Compresión dinámica y estática: <urlCompression doStaticCompression="true" doDynamicCompression="true" />
      Activa la compresión GZIP/deflate para archivos estáticos (CSS, JS) y dinámicos (HTML, XML), reduciendo el ancho de banda utilizado y mejorando el tiempo de carga de las páginas.
    • Optimización de módulos administrados: <modules runAllManagedModulesForAllRequests="false" />
      Impide que los módulos administrados de IIS se ejecuten para solicitudes de archivos estáticos (imágenes, CSS, JS) cuando no es necesario. Mejora el rendimiento al reducir el procesamiento innecesario.
    • Modo de compilación en producción: <compilation debug="false" targetFramework="4.8" />
      Deshabilita el modo de depuración en producción, lo que optimiza el rendimiento (desactiva la compilación en caliente, reduce el consumo de memoria) y evita que se muestren mensajes de error detallados a los usuarios finales.
    • Filtrado de solicitudes y verbos HTTP: Se agregó la siguiente configuración dentro de <system.webServer>:
      <security><requestFiltering><requestLimits maxAllowedContentLength="10485760" /><verbs allowUnlisted="false"><add verb="GET" allowed="true"/><add verb="POST" allowed="true"/></verbs></requestFiltering></security>
      - maxAllowedContentLength: Limita el tamaño del contenido de la petición (10 MB), complementando maxRequestLength.
      - verbs allowUnlisted="false": Bloquea todos los verbos HTTP no listados explícitamente, permitiendo solo GET y POST. Reduce la superficie de ataque contra verbos como DELETE, TRACE, OPTIONS, etc.

📄 Lista completa de objetos del SSO modificados

  • SSO_APP\Digital\src\helper.js
  • SSO_APP\DigitalHelp.aspx
  • SSO_APP\DigitalSign.aspx
  • SSO_APP\InfoChangePass.aspx.vb
  • SSO_APP\InfoNewUser.aspx
  • SSO_APP\Login.aspx
  • SSO_APP\Login.aspx.designer.vb
  • SSO_APP\Login.aspx.vb
  • SSO_APP\PUA\PUAControl.aspx
  • SSO_APP\PUA\src\modalPUA.js
  • SSO_APP\ResetPass.aspx.vb
  • SSO_APP\Styles\bootstrap\dist\js
  • SSO_APP\Styles\bootstrap\dist\js\bootstrap.js
  • SSO_APP\Styles\bootstrap\dist\js\bootstrap.min.js
  • SSO_APP\Styles\bootstrap\Gruntfile.js
  • SSO_APP\Styles\js\Utilitarios.js
  • SSO_APP\Styles\plugins\bower_components\bootstrap-old\Gruntfile.js
  • SSO_APP\Styles\plugins\bower_components\custom-select\Gruntfile.js
  • SSO_APP\SystemManagement.aspx
  • SSO_APP\UpdateUser.aspx.vb
  • SSO_APP\Web.config
  • SSO_BLL\BLL_SSO.vb
  • SSO_BLL\Notification.vb
  • SSO_BLL\SecurityUsers.vb

📄 Security.txt

📌 Importancia

El archivo security.txt (RFC 9116) es un estándar técnico que define un archivo ubicado en /.well-known/security.txt. Su importancia radica en que proporciona un mecanismo automático y uniforme para que los investigadores de seguridad (y herramientas automatizadas) encuentren los contactos, políticas de divulgación y claves de cifrado necesarias para reportar vulnerabilidades de manera confidencial. Sin este archivo, la comunicación depende de canales informales o búsquedas manuales, lo que retrasa la corrección de fallos y aumenta el riesgo de explotación. Es una pieza clave para la coordinación responsable de vulnerabilidades.

Esta aplicación expone el archivo security.txt para todos los dominios del CFIA (no sólo este servidor). Es una medida moderna de seguridad para colaboración en notificación de vulnerabilidades. Brinda respuesta a cualquier petición https://sso.cfia.or.cr/.well-known/security.txt que responderá con el contenido de https://sso.cfia.or.cr/SecurityTXT/SecurityTxtHandler.ashx.

⚙️ Implementación

  1. Publicar el servicio ASHX
    El servicio se encuentra en https://sso.cfia.or.cr/SecurityTXT/SecurityTxtHandler.ashx.
    En App_Data debe existir el archivo security.txt con el contenido mínimo:
    Contact: mailto:gzuniga@cfia.cr
    Expires: 2027-04-14T23:59:59Z
  2. Agregar reglas de servidor globales
    Para que todos los dominios respondan igual se deben agregar dos reglas globales en el archivo C:\Windows\System32\inetsrv\config\applicationHost.config (es normal que <globalRules> no exista, se debe agregar).
    La configuración es:
    <rewrite>
    <globalRules>
    <rule name="Serve security.txt from central handler" stopProcessing="true">
    <match url="^\.well-known/security\.txt$" />
    <action type="Rewrite" url="https://sso.cfia.or.cr/SecurityTXT/SecurityTxtHandler.ashx" />
    </rule>
    <rule name="Redirect root security.txt to .well-known" stopProcessing="true">
    <match url="^security\.txt$" />
    <action type="Redirect" url="/.well-known/security.txt" redirectType="Permanent" />
    </rule>
    </globalRules>
    </rewrite>

    Importante: La URL del servicio siempre será la misma, sin importar el servidor (de producción).
    Para DTT se debe usar la URL de DEV (https://dev-sso.cfia.or.cr/SecurityTXT/SecurityTxtHandler.ashx) pues es la que se ha configurado. DTT no puede consumir nada de Producción.


  3. Instalar el Proxy de ARR (Application Request Routing)
    Si la regla de reescritura apunta a una URL diferente al sitio original, IIS necesita que ARR esté instalado y el proxy habilitado. Esto es necesario para que la reescritura funcione entre diferentes sitios o aplicaciones.
    • Instalar requestRouter_amd64.msi.
    • Abrir el Administrador de IIS y seleccionar el nodo del servidor.
    • Buscar el icono "Application Request Routing Cache". Si no aparece, instalar el módulo ARR desde la Web Platform Installer.
    • Hacer doble clic en "Application Request Routing Cache".
    • En el panel de acciones, hacer clic en "Configuración de proxy del servidor...".
    • Marcar la casilla "Habilitar proxy" y hacer clic en "Aplicar".
    • Reiniciar IIS.

  4. Pruebas
    Basta con abrir las siguientes URLs:
    • Base: https://sso.cfia.or.cr/SecurityTXT/SecurityTxtHandler.ashx
    • Publicado: https://apc.cfia.or.cr/.well-known/security.txt
      https://apc.cfia.or.cr/security.txt
      https://sso.cfia.or.cr/.well-known/security.txt
      https://sso.cfia.or.cr/security.txt
      https://servicios.cfia.or.cr/.well-known/security.txt
      https://servicios.cfia.or.cr/security.txt

⏳ Pendiente

Habilitarlo en Producción.

🔗 Referencia

https://www.hackerone.com/blog/what-securitytxt-file-and-how-can-it-help-your-security-program

📊 Resultados de seguridad

Como verificación del resultado de las medidas de seguridad implementadas, se muestra la mejora en calificación general de seguridad web que brinda Mozilla Observatory.

🔴 Producción

D+
📄 Descargar informe (PDF)
➡️
📈 Esto implica un avance de 5 posiciones en la escala de calificación (de D+ a B), reflejando una mejora sustancial en la postura de seguridad.

📊 Evaluación detallada de CSP según centralcsp.com

🔴 Producción 7%

Seguridad: 0/100
Basic security measures present but significant CSP gaps exist.
Compliance: 0/100
Several compliance gaps found in CSP implementation.
Best Practices: 21/100
Basic practices followed but missing important optimizations.
➡️

🟢 Nuevo 32%

Seguridad: 43/100
Multiple security vulnerabilities found in CSP configuration.
Compliance: 14/100
Several compliance gaps found in CSP implementation.
Best Practices: 41/100
Several deviations from recommended CSP practices.
📊 Mejora significativa en todos los indicadores: Seguridad +43 puntos, Cumplimiento +14 puntos, Buenas Prácticas +20 puntos.

🛠️ Herramientas de análisis de seguridad

HerramientaEnlaceDescripción técnica
Central CSP Evaluator centralcsp.com/features/evaluator Evalúa políticas CSP otorgando puntuaciones de Seguridad, Cumplimiento y Buenas Prácticas (0-100). Detecta comodines peligrosos, unsafe-inline/eval, falta de nonces y problemas de compatibilidad con estándares. Permite exportar resultados.
Google CSP Evaluator csp-evaluator.withgoogle.com Herramienta oficial de Google que analiza políticas CSP y detecta configuraciones inseguras como el uso de unsafe-inline, unsafe-eval, comodines peligrosos (*, data:, blob:) y falta de strict-dynamic. Asigna severidad a cada hallazgo.
Hardenize hardenize.com/report/... Plataforma de análisis continuo de superficie de ataque. Evalúa TLS, DNS, cabeceras de seguridad (CSP, HSTS, CORS) y certificados. Genera informes históricos y alertas de cambios. Permite monitorizar la evolución de la seguridad.
Mozilla Observatory developer.mozilla.org/observatory Herramienta de Mozilla que califica la seguridad de un sitio web de la A+ a la F. Evalúa cabeceras CSP, HSTS, X-Frame-Options, cookies, redirecciones HTTPS, y otros estándares. Genera recomendaciones específicas y permite compartir informes. Es el estándar para medir la postura general.
HostedScan hostedscan.com/dashboard Servicio en la nube para escaneo de vulnerabilidades (OpenVAS) y seguridad web. Realiza análisis de puertos, detección de servicios, evaluación de TLS y verificación de cabeceras de seguridad. Permite programar escaneos periódicos y exportar resultados.
Web-Check (Web-Check.xyz) web-check.xyz/check/... Herramienta de código abierto que mapea la superficie de ataque: perfila el servidor (IIS, versión), analiza SSL/TLS, verifica cabeceras de seguridad (CSP, HSTS, CORS), detecta tecnologías utilizadas (frameworks, CDNs) y revisa DNS. Ideal para un análisis rápido y visual.
CSP Analyzer (Encode64) encode64.com/es/system/csp-analyzer Analizador de CSP en español que valida políticas directamente (pegando la directiva) o mediante URL. Detecta vulnerabilidades como unsafe-inline, unsafe-eval, comodines, falta de nonces, y problemas de compatibilidad con informes. Permite exportar resultados a PDF/JSON. Muy útil para depuración.适合 implementadores.