What is a safe method?

Blindando tu API REST: Guía Esencial

02/11/2023

Valoración: 4.29 (16324 votos)

La seguridad en una API REST no es un añadido de última hora, sino un pilar fundamental que debe integrarse desde el inicio en cualquier proyecto de desarrollo. A diferencia de otras arquitecturas, las APIs RESTful son sin estado, lo que significa que la autenticación y autorización no dependen de sesiones activas en el servidor. Cada petición debe valerse por sí misma, incluyendo credenciales que el servidor debe validar en cada ocasión. Esta característica, aunque ventajosa para la escalabilidad, introduce desafíos de seguridad únicos que todo desarrollador debe conocer y saber cómo mitigar.

How to secure a REST API?
REST API Security isn’t an afterthought. It has to be an integral part of any development project and also for REST APIs. There are multiple ways to secure a RESTful API e.g. basic auth, OAuth, etc. but one thing is sure that RESTful APIs should be stateless – so request authentication/authorization should not depend on sessions.

En esta guía completa, exploraremos los principios de diseño de seguridad, las mejores prácticas de la industria y conceptos clave como los métodos seguros e idempotentes, proporcionándote las herramientas necesarias para construir APIs no solo funcionales, sino también robustas y a prueba de amenazas.

Índice de Contenido

Principios Fundamentales del Diseño de Seguridad

El documento clásico “The Protection of Information in Computer Systems” de Jerome Saltzer y Michael Schroeder estableció ocho principios de diseño que siguen siendo la base de la seguridad informática moderna. Aplicarlos al diseño de tu API REST es un paso crucial para construir un sistema sólido.

1. Mínimo Privilegio (Least Privilege)

Una entidad, ya sea un usuario o un servicio, solo debe tener los permisos estrictamente necesarios para realizar las acciones para las que está autorizada, y nada más. Si un usuario solo necesita leer datos, no debe tener permisos de escritura o eliminación. Los permisos deben añadirse según la necesidad y revocarse en cuanto dejen de ser necesarios.

2. Valores por Defecto a Prueba de Fallos (Fail-Safe Defaults)

El acceso por defecto de cualquier usuario a cualquier recurso del sistema debe ser “denegado”. El permiso para acceder o modificar un recurso debe ser otorgado de manera explícita. Nunca asumas que un usuario tiene acceso; la regla debe ser denegar todo y permitir solo lo específico.

3. Economía del Mecanismo (Economy of Mechanism)

La simplicidad es clave en la seguridad. El diseño de tu sistema de seguridad debe ser lo más simple posible. Cuanto más complejas sean las interfaces y las interacciones entre componentes, más probable es que existan agujeros de seguridad o configuraciones erróneas. Un diseño limpio y comprensible es más fácil de auditar y mantener.

4. Mediación Completa (Complete Mediation)

El sistema debe validar los derechos de acceso a todos sus recursos en cada petición. No se debe confiar en una matriz de permisos cacheada o en una decisión de acceso previa. Si los permisos de un usuario cambian, el sistema debe reflejar ese cambio inmediatamente en la siguiente petición, sin excepciones. Esto evita que un usuario con permisos revocados pueda seguir accediendo a recursos.

What are safe methods in http?
Safe methods are HTTP methods that do not modify resources. For instance, using GET or HEAD on a resource URL, should NEVER change the resource. And untill here it is ok, it is nothing different from what I yek know, but after it assert that: However, this is not completely true. It means: it won't change the resource representation.

5. Diseño Abierto (Open Design)

La seguridad de un sistema no debe depender del secretismo de sus algoritmos o de su diseño. Este principio defiende que el sistema debe ser seguro incluso si su funcionamiento interno es de conocimiento público. La seguridad debe residir en elementos como las claves de cifrado o las contraseñas, no en ocultar cómo funciona el sistema (seguridad por oscuridad).

6. Separación de Privilegios (Separation of Privilege)

Otorgar permisos a una entidad no debería basarse en una única condición. Es mucho más seguro requerir que se cumplan múltiples condiciones para conceder acceso a recursos críticos. Por ejemplo, para realizar una transacción financiera, se podría requerir no solo una contraseña, sino también un segundo factor de autenticación.

7. Mínimo Mecanismo Común (Least Common Mechanism)

Este principio advierte sobre el riesgo de compartir estados o componentes entre diferentes partes del sistema. Si un componente compartido es corrompido, puede afectar a todas las demás partes que dependen de él. Se debe minimizar la cantidad de mecanismos compartidos para limitar el radio de impacto de una posible brecha de seguridad.

8. Aceptabilidad Psicológica (Psychological Acceptability)

Los mecanismos de seguridad no deben hacer que el acceso a un recurso sea más difícil de lo necesario. Si la seguridad es demasiado engorrosa, los usuarios buscarán formas de eludirla, creando nuevas vulnerabilidades. La seguridad debe ser lo más transparente posible y no empeorar significativamente la experiencia del usuario.

Mejores Prácticas para Asegurar una API REST

Más allá de los principios teóricos, existen acciones prácticas y concretas que puedes implementar para fortalecer la seguridad de tu API.

Utiliza Siempre HTTPS

No hay excusa para no usar HTTPS. El cifrado SSL/TLS protege los datos en tránsito entre el cliente y el servidor, incluyendo credenciales de autenticación, tokens y la información sensible que maneja tu API. Sin HTTPS, toda esta información viaja en texto plano, siendo vulnerable a ataques de intermediario (Man-in-the-Middle). Al forzar el uso de SSL, puedes simplificar las credenciales a un token de acceso generado aleatoriamente, enviado de forma segura en las cabeceras de la petición.

How to secure a REST API?
REST API Security isn’t an afterthought. It has to be an integral part of any development project and also for REST APIs. There are multiple ways to secure a RESTful API e.g. basic auth, OAuth, etc. but one thing is sure that RESTful APIs should be stateless – so request authentication/authorization should not depend on sessions.

Almacena Contraseñas con Hash

Nunca, bajo ninguna circunstancia, almacenes contraseñas en texto plano. Utiliza algoritmos de hash fuertes y modernos como bcrypt, scrypt o PBKDF2. Estos algoritmos están diseñados para ser lentos computacionalmente, lo que dificulta enormemente los ataques de fuerza bruta o de diccionario, incluso si un atacante logra acceder a tu base de datos.

No Expongas Información Sensible en las URLs

Los nombres de usuario, contraseñas, tokens de sesión y claves de API nunca deben aparecer en la URL. Las URLs se registran en los logs del servidor web, en el historial del navegador y pueden ser compartidas o cacheadas, exponiendo fácilmente información crítica. Por ejemplo, una URL como `https://api.ejemplo.com/usuarios/123/accion?apiKey=ABCDE12345` es una pésima práctica. La información sensible debe ir en las cabeceras de la petición (como la cabecera `Authorization`) o en el cuerpo de una petición POST.

Considera el uso de OAuth 2.0

Aunque la autenticación básica sobre HTTPS puede ser suficiente para muchos casos, OAuth 2.0 es el estándar de la industria para la autorización delegada. Permite que una aplicación de terceros obtenga acceso limitado a un servicio HTTP en nombre del propietario de un recurso. Es ideal para escenarios donde los usuarios necesitan conceder permisos a otras aplicaciones para que accedan a sus datos sin compartir sus credenciales directas.

Añade una Marca de Tiempo a las Peticiones

Incluir una marca de tiempo (timestamp) en una cabecera HTTP personalizada en cada petición puede ayudar a mitigar ataques de repetición básicos. El servidor compara la marca de tiempo de la petición con su hora actual y solo la acepta si está dentro de un margen de tiempo razonable (por ejemplo, 30 segundos). Esto evita que un atacante capture una petición válida y la reenvíe indefinidamente para intentar explotar el sistema.

Valida Rigurosamente los Datos de Entrada

Toda la información que llega a tu API debe ser tratada como no confiable. Valida cada parámetro de entrada en la capa más externa de tu aplicación, antes de que llegue a la lógica de negocio. Verifica tipos de datos, longitudes, formatos y rangos permitidos. Una validación estricta es tu primera línea de defensa contra ataques como la inyección SQL, Cross-Site Scripting (XSS) y otros ataques basados en la manipulación de entradas.

Entendiendo los Métodos HTTP: Seguridad vs. Idempotencia

Para diseñar una API REST robusta, es fundamental comprender la semántica de los métodos HTTP, especialmente los conceptos de métodos seguros y métodos idempotentes.

Is a safe request method idempotent?
Safe request handling leaves the resource in the same state, so a safe method is necessarily also idempotent. A request method is considered "idempotent" if the intended effect on the server of multiple identical requests with that method is the same as the effect for a single such request.

Métodos Seguros

Un método HTTP se considera seguro si no modifica el estado del recurso en el servidor. Su propósito es únicamente la recuperación de datos. Los métodos GET, HEAD, OPTIONS y TRACE son seguros. Usar un GET sobre una URL no debería cambiar el recurso. Sin embargo, esto no es del todo absoluto: un método seguro puede realizar acciones en el servidor (como registrar una visita o actualizar una caché), pero no debe alterar la representación principal del recurso. Por ejemplo, una petición como `GET /blog/1234/eliminar` es incorrecta, ya que la semántica de GET implica solo lectura, no una acción destructiva.

Métodos Idempotentes

Un método HTTP es idempotente si realizar la misma petición múltiples veces produce el mismo efecto en el recurso que realizarla una sola vez. No importa si llamas al método una vez o diez veces, el estado final del recurso será el mismo. Por ejemplo, `a = 4;` es una operación idempotente, mientras que `a++;` no lo es.

La idempotencia es vital para construir APIs tolerantes a fallos. Imagina que un cliente envía una petición PUT para actualizar un recurso, pero sufre un timeout. ¿Se actualizó el recurso? ¿Puede reenviar la petición de forma segura? Como PUT es idempotente, la respuesta es sí. Puede reenviar la petición hasta recibir una respuesta exitosa, con la certeza de que no causará efectos secundarios no deseados. Los métodos PUT y DELETE son idempotentes, pero no seguros (porque modifican el recurso). POST no es ni seguro ni idempotente.

Tabla Comparativa de Métodos HTTP

Método HTTPIdempotenteSeguro
OPTIONS
GET
HEAD
PUTNo
POSTNoNo
DELETENo
PATCHNoNo

Preguntas Frecuentes (FAQ)

¿Por qué no debo poner mi clave de API en la URL?

Exponer una clave de API en la URL es un riesgo de seguridad grave porque las URLs quedan registradas en múltiples lugares: el historial del navegador, los logs del servidor web y los logs de cualquier proxy intermedio. Cualquiera con acceso a estos registros podría robar la clave y suplantar la identidad de tu aplicación.

¿Un método seguro es siempre idempotente?

Sí. Por definición, un método seguro no cambia el estado del recurso. Dado que no hay cambios, realizar la petición una o múltiples veces no alterará el estado del recurso, lo que cumple con la definición de idempotencia. Por lo tanto, todos los métodos seguros son inherentemente idempotentes.

Si uso HTTPS, ¿necesito preocuparme por otras medidas de seguridad?

Absolutamente. HTTPS es fundamental, pero solo protege los datos en tránsito. No te protege contra vulnerabilidades en tu aplicación, como una validación de entrada deficiente (que podría permitir inyección SQL), un control de acceso roto, contraseñas débiles o fallos en la lógica de negocio. La seguridad debe ser un enfoque en capas.

Si quieres conocer otros artículos parecidos a Blindando tu API REST: Guía Esencial puedes visitar la categoría Juegos.

Subir