Autorización y control de acceso
La autenticación demuestra quién eres. La autorización decide qué puedes tocar. El fallo más común y más dañino en las aplicaciones modernas es equivocarse en la segunda: un usuario con sesión iniciada que lee o cambia datos que no son suyos.
Lista de verificación
- Comprueba la propiedad en cada acceso a un objeto. Para cada ruta que reciba un id (una factura, una nota, un proyecto, un mensaje), confirma que el usuario actual es dueño de ese registro concreto o puede acceder a él antes de devolverlo o modificarlo. Esto es Broken Object Level Authorization (BOLA), también llamado IDOR, y es el riesgo número uno de OWASP.
- Filtra por propietario, no solo por id. Una consulta como
SELECT * FROM invoices WHERE id = ?es un IDOR. Cámbiala aWHERE id = ? AND owner_id = ?y devuelve 404 cuando no haya coincidencia. - No confíes en el cliente para ocultar cosas. Un botón oculto o un enlace que no aparece no es control de acceso. La comprobación debe estar en el servidor.
- Mantén la autorización al refactorizar. Las comprobaciones de acceso añadidas en un cambio a menudo se pierden en el siguiente. Vuelve a probar la propiedad después de cada cambio en las rutas de datos.
- Aplica seguridad a nivel de fila (row-level security) en la base de datos cuando tu plataforma lo admita, para que una comprobación olvidada en el código siga siendo detectada por la capa de datos.
- Protege cada ruta de administración e interna. Confirma que quien hace la llamada es realmente administrador desde una fuente de confianza (un rol del lado del servidor, no un campo que el usuario pueda definir), y mantén las rutas solo internas inaccesibles desde internet público.
- Aísla a los inquilinos. En una aplicación multi-inquilino, cada consulta y cada ruta de archivo deben estar limitadas al inquilino del solicitante a través de un único punto de control, para que un cliente nunca pueda llegar a los datos o archivos de otro.
- Confina las rutas de archivo. Cuando una solicitud nombra un archivo, resuélvelo y confirma que permanece dentro del directorio permitido, y que la comprobación se detiene en un separador de ruta para que una carpeta hermana con un nombre más largo no sea accesible.
Cómo probar
- Crea dos cuentas. Como la cuenta A, solicita directamente los ids de objetos de la cuenta B. No debe devolverse nada de B.
- Llama a una ruta de administración con el token de un usuario normal. Espera un 403.
- Solicita rutas con estilo
../y con prefijo de carpeta hermana en cualquier endpoint de archivos.