📊 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).
📈 Evolución de la calificación de seguridad
📊 Progreso por áreas clave
0
1
2
3
4
5
6
7
8
9
10
11
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-srcystyle-srca dominios concretos. - Aplicar la configuración de CORS basada en la lista de orígenes recopilada (Taller Seguridad IV).
- Habilitar
security.txten 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:
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:
- Requisito previo: Asegurar el uso de HTTPS con un certificado SSL válido en el puerto 443.
- Habilitar en el Registro: Ejecute regedit, navegue a
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\HTTP\Parameters, cree un nuevo valor DWORD (32-bit) llamadoEnableHttp3y establézcalo en 1. - 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 - Reiniciar el servidor.
- 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. - 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.
- Verificar regla en Firewall de Windows:
- 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)
- 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.
- 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: SeleccionaRESPONSE_Strict_Transport_Security.
- Variable value: Selecciona Matches the pattern y usa Regular Expressions.
- Pattern:.*(coincide con cualquier valor actual del encabezado).
- 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.
- 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.
- Verificación: Una vez aplicada, puedes probar desde la consola del navegador en un subdominio. La cabecera
Strict-Transport-Securitydebería aparecer en las respuestas HTTPS. La configuración resultante enweb.configdebe ser:
<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:
.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 (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.
⚙️ Logging (configuración de logging de orígenes)
- 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.
- 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.
- Finalizar la configuración:
- En la ventana "W3C Logging Fields", asegúrate de que tu nuevo campo
X-Originesté marcado y haz clic en OK. - En la ventana principal de "Logging", haz clic en "Apply" en el panel de acciones.
- En la ventana "W3C Logging Fields", asegúrate de que tu nuevo campo
- 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.
- Los logs se seguirán guardando en tu ruta habitual de logs de IIS (por ejemplo,
- 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 GreenAl ejecutar este análisis, se obtiene 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 la lista blanca de CORS.
⚙️ Implementación de CORS con lista blanca
Una vez se cuente con la lista blanca para consumo de servicios y conexiones al CFIA, se debe configurar en el servidor. En C:\Windows\System32\inetsrv\config\applicationHost.config se debe agregar la lista de dominios válidos para consumir servicios CFIA. Se busca la etiqueta <rewrite> y se agrega lo siguiente:
<rewriteMaps>
<rewriteMap name="AllowedOrigins" defaultValue="">
<add key="https://cfia.aurainteractiva.com" value="https://cfia.aurainteractiva.com" />
<add key="https://cfia.zendesk.com" value="https://cfia.zendesk.com" />
<add key="https://tramitesconstruccion.go.cr" value="https://tramitesconstruccion.go.cr" />
</rewriteMap>
</rewriteMaps>
<outboundRules>
<!-- Regla 1: Cuando no hay cabecera Origin (petición same-origin) -->
<rule name="Set-CORS-Header-Empty-Origin" stopProcessing="true">
<match serverVariable="RESPONSE_Access_Control_Allow_Origin" pattern=".*" />
<conditions logicalGrouping="MatchAll">
<add input="{HTTP_ORIGIN}" pattern="^$" />
</conditions>
<action type="Rewrite" value="{HTTP_HOST}" />
</rule>
<!-- Regla 2: Cuando es del dominio cfia o de la lista blanca -->
<rule name="Set-CORS-Header" stopProcessing="false">
<match serverVariable="RESPONSE_Access_Control_Allow_Origin" pattern=".*" />
<conditions logicalGrouping="MatchAny" trackAllCaptures="true">
<add input="{HTTP_ORIGIN}" pattern="^https?://([^/]+\.)?cfia\.or\.cr$"" />
<add input="{AllowedOrigins:{HTTP_ORIGIN}}" pattern=".+" />
</conditions>
<action type="Rewrite" value="{HTTP_ORIGIN}" />
</rule>
</outboundRules>
Importante:
- La validación bloquea los intentos de suplantación mediante dominios que añadan sufijos después de cfia.or.cr serán correctamente bloqueados.
- Al activar CORS se debe utilizar la cabecera Access-Control-Allow-Methods. Esta es utilizada por los navegadores durante las peticiones de "preflight" (una verificación previa que el navegador realiza para métodos no básicos como PUT, DELETE, o cuando se usan ciertas cabeceras personalizadas).
Access-Control-Allow-Origin, es recomendable añadir la cabecera Vary para evitar problemas de caché. Agrega la siguiente línea en tu sección <customHeaders>:
Ahora, para evitar errores, es necesario eliminar esta cabecera de los web.config que los incluyen:
Es mejor buscar en todo D:\IIS\ *.config la siguiente cadena:
access-control-allow-headers
- D:\IIS\DEV\APT\Publico\Seguro\APT\bin\CFIA.APT.UI.dll.config
- D:\IIS\DEV\APT\Publico\Seguro\Apt.FileService\Web.config
- D:\IIS\DEV\APT\Publico\Seguro\APT2\bin\CFIA.APT.UI.dll.config
- D:\IIS\DEV\APT\Publico\Seguro\APT2\Web.config
- D:\IIS\DEV\APT\Publico\Seguro\VisorLaminas\web.config
- D:\IIS\DEV\Servicios\Privado\Normal\WS_Certificaciones\Web.config
- D:\IIS\DEV\Servicios\Publico\Seguro\Certificaciones\Web.config
- D:\IIS\DEV\Servicios\Publico\Seguro\CFIA\web.config
- D:\IIS\DEV\Servicios\Publico\Seguro\Expediente\Web.config
- D:\IIS\DEV\Servicios\Publico\Seguro\VisorArchivos\Web.config
- D:\IIS\DEV\SSO\Publico\Seguro\SSO\bin\SSO_APP.dll.config
- D:\IIS\TEST\APT\Publico\Seguro\Apt.FileService\Web.config
- D:\IIS\TEST\APT\Publico\Seguro\APT2_Protocolo\Web1.config
- D:\IIS\TEST\APT\Publico\Seguro\VisorLaminas\web.config
- D:\IIS\TEST\Servicios\Privado\Normal\WS_Certificaciones\Web.config
- D:\IIS\TEST\Servicios\Publico\Seguro\Certificaciones\Web.config
- D:\IIS\TEST\Servicios\Publico\Seguro\CFIA\web.config
- D:\IIS\TEST\Servicios\Publico\Seguro\Expediente\Web.config
- D:\IIS\TEST\Servicios\Publico\Seguro\VisorArchivos\Web.config
- D:\IIS\TEST\SSO\Publico\Seguro\SSO\bin\SSO_APP.dll.config
- D:\IIS\TRA\APT\Publico\Seguro\Apt.FileService\Web.config
- D:\IIS\TRA\APT\Publico\Seguro\VisorLaminas\web.config
- D:\IIS\TRA\Servicios\Privado\Normal\WS_Certificaciones\Web.config
- D:\IIS\TRA\Servicios\Publico\Seguro\Certificaciones\Web.config
- D:\IIS\TRA\Servicios\Publico\Seguro\CFIA\web.config
- D:\IIS\TRA\Servicios\Publico\Seguro\Expediente\Web.config
- D:\IIS\TRA\Servicios\Publico\Seguro\VisorArchivos\Web.config
- D:\IIS\TRA\SSO\Publico\Seguro\SSO\bin\SSO_APP.dll.config
🧪 Método de prueba directa
Se puede revisar directamente la configuración del CORS desde el navegador (network) o desde DOS.
Prueba exitosa (debe mostrar la cabecera CORS):
- curl -I -H "Origin: https://tramitesconstruccion.go.cr" https://dev-sso.cfia.or.cr
- curl -I -H "Origin: https://apc.cfia.or.cr" https://dev-sso.cfia.or.cr
- curl -I -H "Origin: https://test-apc.cfia.or.cr" https://dev-sso.cfia.or.cr
- curl -I https://dev-sso.cfia.or.cr/tu-api
Prueba de bloqueo (no debe devolver la cabecera CORS):
📜 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ísicaD:\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:
| Directiva | Valor 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):
CSP_Nuevo (mejorado, aplicado):
⏳ 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
httpRuntimepara 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 cabeceraX-AspNet-Versionen 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), complementandomaxRequestLength.
-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. - Mejora HTML responsive para páginas usadas por la App: Se mejoraron algunas pantallas para que su visualización desde dispositivos móviles sea más clara (responsive):
FindUser.aspx, ResetPass.aspx, UpdateUser.aspx
📄 Lista completa de objetos del SSO modificados
- SSO_APP\Digital\src
- SSO_APP\Digital\src\helper.js
- SSO_APP\DigitalHelp.aspx
- SSO_APP\FindUser.aspx
- SSO_APP\FindUserAccess.aspx
- SSO_APP\InfoChangePass.aspx
- SSO_APP\InfoChangePass.aspx.designer.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
- SSO_APP\SelectUser.aspx
- SSO_APP\ShowNews.aspx
- SSO_APP\Site.Master
- SSO_APP\SMSResetPass.aspx
- SSO_APP\
- SSO_APP.vbproj
- 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\css\jquery.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
- SSO_APP\UserAddAccess.aspx
- SSO_APP\UserData.aspx
- SSO_APP\UserDataSec.aspx
- SSO_APP\Utilitarios.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
- Publicar el servicio ASHX
El servicio se encuentra enhttps://sso.cfia.or.cr/SecurityTXT/SecurityTxtHandler.ashx.
EnApp_Datadebe existir el archivosecurity.txtcon el contenido mínimo:Contact: mailto:gzuniga@cfia.cr
Expires: 2027-04-14T23:59:59Z - Agregar reglas de servidor globales
Para que todos los dominios respondan igual se deben agregar dos reglas globales en el archivoC:\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.
- 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.
- Instalar
- 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
- Base:
⏳ 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.
📊 Evaluación detallada de CSP según centralcsp.com
🔴 Producción 7%
🟢 Nuevo 32%
🛠️ Herramientas de análisis de seguridad
| Herramienta | Enlace | Descripció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. |