Directrices

Autenticación y autorización

El tema de la autenticación (AuthN) y la autorización (AuthZ) es sumamente importante debido a la frecuencia con la que aparecen vulnerabilidades relacionadas con ambos. Dado que surgen con tanta regularidad, esto suele significar que existe cierta incertidumbre sobre qué son o incluso qué es lo que las provoca.

Como recordatorio, cada término abarca lo siguiente:

  • Autenticación: ¿Quién es el usuario?
  • Autorización: ¿A qué debería tener acceso el usuario?

Los analizaremos por separado a continuación.

Autenticación (fallos de identificación y autenticación)

Una autenticación inadecuada puede abarcar una gran variedad de vulnerabilidades, tales como:

  • La ausencia de autenticación en una página o punto final específico
  • Falta de protección contra ataques de fuerza bruta (relleno de credenciales)
  • Procesos inseguros de recuperación de cuentas o contraseñas
  • Generación, validación, caducidad, transmisión o almacenamiento inseguros de tokens de autenticación
  • Validación incorrecta o inexistente de que el usuario se ha autenticado con 2FA (cuando corresponda)

El primer elemento de la lista (ausencia de autenticación) es, con diferencia, el problema más común observado en entornos reales. Muchas veces, un desarrollador debe anotar o configurar explícitamente el nivel de autenticación requerido por una página o punto final, y ese paso puede pasarse por alto fácilmente.

Es una buena práctica asegurarse de que un sistema falle de forma cerrada, en lugar de fallar de forma abierta. Por lo tanto, en lugar de anotar cada punto final con la información de que requieren una sesión de usuario autenticada, el valor predeterminado debería ser que todas las rutas requieran una sesión de usuario autenticada a menos que se haya anulado específicamente. Hacer esto puede reducir drásticamente el margen de error.

Autorización (control de acceso deficiente)

Los problemas de autorización pueden presentarse de varias formas muy comunes:

  • Referencias directas a objetos inseguras (IDOR)
  • Falta de control de acceso a nivel de función (falta de AuthZ)
  • Escalada de privilegios (horizontal o vertical)

Referencias directas a objetos inseguras

Los objetos suelen tener identificadores únicos (ID) que se utilizan como clave para hacer referencia a ellos. Cuando un usuario envía una solicitud para ver un pedido, una cuenta o algo similar, normalmente contiene este ID. Una "referencia directa a objeto insegura" ocurre cuando la aplicación no valida si el usuario (o la falta de él) debería poder acceder a ese objeto específico.

Falta de control de acceso a nivel de función

Otra vulnerabilidad muy común es la ausencia de comprobaciones de autorización para una página o punto final (a diferencia de un objeto).

Dependiendo del marco de trabajo utilizado, es común que los desarrolladores tengan que comprobar la autorización en el controlador o anotar el punto final y especificar los requisitos necesarios para invocarlo.

Desafortunadamente, estos pasos adicionales también son muy fáciles de olvidar, lo que a menudo explica cómo terminan ocurriendo algunas vulnerabilidades de autorización.

Recomendaciones

Predeterminar el acceso restringido en lugar del abierto

Tanto en la autenticación como en la autorización, es fundamental aplicar el principio de restringir el acceso por defecto en lugar de dejarlo abierto.

Dependiendo de su lenguaje o framework, es una buena práctica asegurarse de que todas las rutas de acceso a su aplicación requieran, por defecto, una sesión autenticada con los roles o permisos más elevados posibles. Esto obliga al desarrollador a anular explícitamente los requisitos de la ruta.

cs

// Asegurar que el comportamiento predeterminado sea autenticar las solicitudes y verificar si son administrador
[Authenticate]
[Authorize("Admin")]
public class SecureController : Controller
{

}

public class MyController : SecureController
{

    // Anula el atributo Authorize heredado para permitir que cualquier usuario acceda a la página
    [Authorize("User")]
    public Page ShowUserProfile() {
        
    }   

    // Solo puede ser accedido por un usuario administrador
    public Page ShowAdminPage() { 

   }

    // Anula el atributo Authenticate y Authorize para permitirme el acceso
    [AllowAnonymous]
    public Page ShowLoginPage() {
       
    } 

}

Aplicar controles de autorización en los servicios

Al acceder a los datos, es extremadamente importante garantizar que todo acceso a la información aplique los controles de acceso y autorización pertinentes de manera uniforme. Por lo general, esto se logra mediante el uso de servicios de dominio.

Más ejemplos

A continuación, presentamos una breve colección de ejemplos que ilustran claramente la diferencia entre una autenticación y autorización segura frente a una insegura.

C# - inseguro

Falta de autenticación

public class AdminController : Controller
{

    // INSEGURO: No verifica si el usuario ha iniciado sesión antes de mostrar una página de administración
    public Page ShowAdminPage() {

    }

}

Falta de autorización

[Authenticate]
public class AdminController : Controller
{

    // INSEGURO: No verifica la autorización del usuario antes de mostrar una página de administración public Page ShowAdminPage() {

    }
‍
}

C# - seguro

[Authenticate]
[Authorize("Admin")]
public class AdminController : Controller
{
‍
    // SEGURO: Verifica tanto que el usuario haya iniciado sesión como que tenga el rol de administrador
    public Page ShowAdminPage() {

    }

}
Eslogan

Programación segura y práctica

Explore las directrices de programación segura para comprender y mitigar vulnerabilidades de software como el OWASP Top 10, y sumérjase en misiones de formación guiada para practicar en simulaciones de aplicaciones del mundo real.

Más directrices
Reservar una demostración