Por framework
Seguridad en ASP.NET Core — una referencia de endurecimiento para producción
Una referencia de endurecimiento para producción de ASP.NET Core: una lista de verificación por prioridad más errores de producción, secretos (User Secrets/Key Vault), CVE de NuGet, autorización, over-posting, deserialización y SSRF. Defensiva, sin pasos de ataque.
Para: cualquiera que gestione una aplicación o API en ASP.NET Core. Aquí no hay pasos de ataque — esta es una referencia de trabajo para el endurecimiento: una lista de verificación ordenada por prioridad, guía por área y autoverificación. Para el panorama entre frameworks, consulta el centro de seguridad por framework.
Lista de endurecimiento ordenada por prioridad
Recorre esta tabla de arriba abajo. P0 es un prerrequisito, P1 es la fuente más frecuente de incidentes, P2 es higiene operativa continua.
P0 ── Prerrequisito (hazlo primero)
Sin errores detallados en producción / externalizar los secretos / parchear rápido los CVE de dependencias NuGet
P1 ── Principal fuente de incidentes
Autorización ([Authorize], denegación por defecto, propietario) / defensa contra over-posting (DTOs/[Bind])
P2 ── Higiene operativa
Deserialización insegura / HTTPS, cabeceras, antiforgery / SSRF
| Prioridad | Control | Detalles (ASP.NET Core) |
|---|---|---|
| P0 | Errores de producción | UseExceptionHandler. No muestres la Developer Exception Page/detalle en producción (comprobación de entorno correcta) |
| P0 | Externalizar secretos | No los codifiques en appsettings.json. Desarrollo = User Secrets, producción = env/Key Vault |
| P0 | CVE de dependencias NuGet | Monitoriza con dotnet list package --vulnerable/osv-scanner; juzga por la versión en ejecución, parchea rápido |
| P1 | Autorización explícita | [Authorize] + denegación por defecto (política de reserva) + comprobaciones basadas en recurso/propietario |
| P1 | Defensa contra over-posting | Haz binding a un DTO, no a la entidad directamente. Usa [Bind] para limitar los campos aceptados |
| P2 | Deserialización | No uses BinaryFormatter. No restaures datos no confiables con un formato inseguro |
| P2 | HTTPS/cabeceras/CSRF | UseHttpsRedirection, UseHsts, antiforgery (CSRF), atributos de cookie |
| P2 | SSRF | Lista de permitidos para las peticiones del lado del servidor + bloquear IPs internas/metadatos |
1. Exposición de errores en producción (P0)
- En producción, cambia a un error genérico mediante
UseExceptionHandlery no muestres la Developer Exception Page/detalle (acierta la comprobación de entorno, p. ej.ASPNETCORE_ENVIRONMENT=Production). - No filtres trazas de pila ni estructura interna externamente.
2. Externalizar secretos (P0)
- No codifiques cadenas de conexión ni claves en appsettings.json. Usa User Secrets en desarrollo y variables de entorno o un gestor de secretos en la nube (Key Vault) en producción.
- appsettings.json se filtra fácilmente mediante un commit accidental o exposición. No lo incluyas en el repositorio ni lo coloques en un directorio público (→ mantén los secretos fuera de los directorios públicos). Rota de inmediato si se filtra.
3. CVE de dependencias NuGet (P0)
- Monitoriza de forma automática los CVE conocidos con
dotnet list package --vulnerableu osv-scanner, juzga por la versión en ejecución y parchea rápido (→ monitorizar los CVE de dependencias · el manual de respuesta a vulnerabilidades). - Mantén .NET en una versión con soporte y no dejes versiones EOL en su sitio.
4. Autorización (P1 — la principal fuente)
Común (peligroso)
- olvidar
[Authorize]en un endpoint - autenticado, pero sin comprobación de propietario
- el valor por defecto se inclina a «permitir», los no autenticados pasan
- sin diseño de roles/políticas, comprobaciones ad-hoc
Correcto
[Authorize]+ denegación por defecto mediante una política de reserva- basada en roles/políticas + autorización basada en recurso para la propiedad
- verificado en cada ruta de lectura/actualización/borrado
- autorización construida explícitamente, no dejada a los valores por defecto
Consulta qué es el IDOR. La autenticación y la autorización son distintas; autoriza cerca de los datos.
5. Over-posting (P1)
- No hagas binding a las entidades directamente. Haz binding a un DTO solo de entrada y acepta únicamente los campos que necesitas.
- O usa
[Bind]para limitar explícitamente los campos aceptados. No dejes que un flag de privilegio se sobrescriba desde la entrada externa.
6. Deserialización insegura y entrada (P2)
- No uses
BinaryFormatter(obsoleto/inseguro). No restaures datos no confiables con un formato inseguro (puede llevar a RCE en las condiciones adecuadas) (→ qué es el RCE). - Valida la entrada con validación de modelo (data annotations, etc.) para tipo/rango/valores permitidos antes de usarla.
7. HTTPS, cabeceras, antiforgery (P2)
- Usa
UseHttpsRedirection+UseHstspara forzar HTTPS, y marca las cookies como secure/httponly/samesite. - Usa tokens antiforgery (defensa CSRF) en formularios/peticiones que cambian estado (→ qué es el CSRF).
- Añade cabeceras de seguridad (comprueba tu propio sitio con el verificador de cabeceras de seguridad).
8. SSRF y peticiones del lado del servidor (P2)
- La obtención del lado del servidor (
HttpClient, etc.) de URLs proporcionadas por el usuario debe restringir los destinos a una lista de permitidos y bloquear el alcance a IPs internas/metadatos (→ qué es el SSRF). Valida las subidas y almacénalas fuera de la superficie pública.
Verifica: ¿está tu ASP.NET Core realmente endurecido?
Construirlo no es el final — solo está hecho una vez que lo has comprobado. Estas son autocomprobaciones defensivas contra tu propio entorno.
Sin Developer Exception Page en producción
Los secretos no están en la config/repositorio
appsettings.json, y que no hay secretos en el repositorio.La autorización se sostiene
Dependencias y HTTPS/cabeceras
dotnet list package --vulnerable/osv está limpio, y que HTTPS/HSTS están presentes mediante el verificador de cabeceras.La opinión de este sitio: aun sobre una base sólida, la configuración y la autorización dependen de ti
ASP.NET Core tiene mecanismos sólidos para la autenticación, la autorización y la protección de datos, pero la configuración de producción y aplicar la autorización son cosas que debes acertar por entorno y por endpoint. Este sitio usa una pila distinta, pero el principio es el mismo: no filtres detalles internos en producción, mantén los secretos fuera de la configuración, escribe siempre la autorización en los puntos de entrada públicos, y monitoriza las dependencias en busca de CVE. Una base sólida solo rinde con una configuración correcta y una autorización explícita.
Lee a continuación
- Centro: seguridad por framework · seguridad en Spring Boot (también empresarial, forma de dependencia/autorización similar)
- Práctica: el manual de respuesta a vulnerabilidades · monitorizar los CVE de dependencias · mantén los secretos fuera de los directorios públicos
- Glosario: qué es el IDOR · qué es el RCE · CSRF · SSRF
- Herramientas: verificador de cabeceras de seguridad
FAQ
Q¿Qué debo hacer primero para asegurar ASP.NET Core?
Los tres elementos P0: (1) no muestres la Developer Exception Page / errores detallados en producción (UseExceptionHandler, comprobación de entorno correcta); (2) externaliza los secretos en lugar de codificarlos en appsettings.json (User Secrets en desarrollo, variables de entorno o Key Vault en producción); (3) monitoriza de forma automática los CVE de dependencias NuGet y parchea rápido, juzgando por la versión en ejecución. Luego, pasa a la autorización ([Authorize], denegación por defecto) y a las defensas contra over-posting.
Q¿Dónde deben ir los secretos (cadenas de conexión, claves de API)?
La regla es: no codificados en appsettings.json. En desarrollo usa User Secrets; en producción cárgalos desde variables de entorno o un gestor de secretos en la nube (Key Vault). appsettings.json tiende a acabar en el repositorio y se filtra fácilmente mediante un directorio público o un commit accidental. Si uno se filtra, rota la cadena de conexión o la clave de inmediato.
Q¿Cómo evito olvidar los atributos de autorización?
Olvida [Authorize] en un controlador o endpoint y cualquiera puede alcanzarlo sin autenticación. Inclina el valor por defecto hacia denegar (una política de reserva que rechaza las peticiones no autenticadas), haz los permisos explícitos con autorización basada en roles/políticas, y escribe comprobaciones de propietario del recurso (autorización basada en recurso). No te quedes en «con sesión iniciada = permitido» — verifica también al propietario del objetivo.
Q¿Qué es el over-posting?
Si el model binding acepta todos los campos en una entidad, campos inesperados que el usuario envió (como un flag de privilegio) pueden sobrescribirse — eso es over-posting. La solución es hacer binding a un DTO solo de entrada, o usar [Bind] para limitar explícitamente los campos aceptados. No hagas binding a las entidades directamente.
Q¿Por qué es peligrosa la deserialización insegura?
Restaurar datos no confiables con un deserializador inseguro como BinaryFormatter puede, en las condiciones adecuadas, llevar a la ejecución remota de código (RCE). BinaryFormatter se considera obsoleto/inseguro — no lo uses. Verifica la procedencia de los datos de origen externo y restringe a un formato seguro (p. ej. JSON correctamente configurado) donde sea necesario.