Skip to main content

¿Cómo proteger una API REST?

Escrito por
blog feature snyk container custom base recommendations

27 de junio de 2024

0 minutos de lectura
How to Secure a REST API

Como desarrolladores, a menudo trabajamos con API REST al integrarnos con sistemas de terceros o conectar sistemas de frontend y backend en el trabajo. Las API, y en particular las API REST, son fundamentales para las aplicaciones web modernas, ya que nos permiten crear, leer, actualizar y eliminar datos mediante HTTP. Sin embargo, como toda tecnología, presentan sus propios desafíos de seguridad. Analicemos estos desafíos y veamos cómo proteger las aplicaciones que usan API REST.

¿Qué es una API REST?

Las API REST (transferencia de estado representacional) son un conjunto de convenciones para diseñar aplicaciones en red. Usan protocolos HTTP para enviar y recibir datos y pueden utilizarse con cualquier lenguaje de programación que pueda enviar solicitudes HTTP. Esto las hace sumamente versátiles y muy utilizadas en el desarrollo web.

Sin embargo, esta versatilidad también las convierte en un objetivo de las ciberamenazas, por lo que siempre debes priorizar el desarrollo de software seguro, por ejemplo, implementando los 10 controles proactivos principales de OWASP. Sin las medidas de seguridad adecuadas, las API REST pueden exponer datos confidenciales o incluso convertirse en un punto de entrada para que los atacantes comprometan tu sistema.

Amenazas de seguridad comunes para las API REST

Hay varias amenazas de seguridad comunes para las API REST que los desarrolladores deben conocer:

  1. Ataques de inyección: Ocurren cuando un atacante envía datos maliciosos como parte de un comando o una consulta y engaña al intérprete para que ejecute comandos no deseados o acceda a datos sin autorización. Por ejemplo, un ataque de inyección SQL puede manipular las consultas a la base de datos de tu API y provocar filtraciones o modificaciones no autorizadas de datos.

  2. Autenticación deficiente: Si los mecanismos de autenticación de tu API están implementados incorrectamente, los atacantes pueden suplantar a otros usuarios o incluso obtener privilegios administrativos. Esto ocurrió en la filtración de datos de Reddit de 2018, cuando los hackers lograron eludir la autenticación de dos factores basada en SMS.

  3. Exposición de datos confidenciales: Las API suelen manejar datos confidenciales, como credenciales de usuario o información personal. Si estos datos no están protegidos adecuadamente, pueden ser interceptados o filtrados, lo que puede dar lugar a graves vulneraciones de la privacidad.

  4. Falta de limitación de solicitudes: Sin límites de solicitudes, tu API es vulnerable a ataques de fuerza bruta, en los que un atacante realiza solicitudes repetidas para intentar adivinar las credenciales de los usuarios o sobrecargar tu sistema. Este fue un factor clave en el ataque a Dyn de 2016, que dejó fuera de servicio sitios web importantes como Twitter y Netflix. La limitación de solicitudes suele implementarse como parte del middleware y se considera una práctica recomendada para proteger los gateways de API.

  5. Dependencias inseguras: Si tu API depende de bibliotecas o frameworks de terceros con vulnerabilidades conocidas, los atacantes pueden aprovecharlas. Este es un problema común en el software de código abierto, como se vio en la filtración de datos de Equifax de 2017, en la que se explotó una vulnerabilidad de Apache Struts.

Puedes mitigar estas amenazas siguiendo las prácticas recomendadas para proteger las API REST, como usar técnicas de codificación segura, implementar mecanismos sólidos de autenticación y autorización, cifrar los datos confidenciales y utilizar herramientas como Snyk Code y Snyk Open Source para detectar y corregir vulnerabilidades en tu código y sus dependencias.

En los siguientes capítulos, exploraremos estas prácticas recomendadas y cómo implementarlas para proteger tus aplicaciones de API REST.

1. Implementa mecanismos sólidos de autenticación y autorización

Al proteger una API REST, implementar mecanismos sólidos de autenticación y autorización es la primera línea de defensa. Así te aseguras de que solo los usuarios autenticados y autorizados puedan acceder a los endpoints de la API.

La autenticación segura es el proceso de confirmar que un usuario es quien dice ser. Para proteger una API REST, es fundamental que el proceso de autenticación sea seguro y evite el acceso no autorizado. Por ejemplo, en 2019, una filtración de datos en Facebook expuso la información personal de casi 50 millones de usuarios. La filtración se debió a un problema en el mecanismo de autenticación, lo que puso de relieve la importancia de contar con una autenticación segura.

Snyk Code puede ayudarte a detectar posibles vulnerabilidades de autenticación en tu código, como credenciales codificadas directamente o la falta de límites de solicitudes, que podrían dar lugar a ataques de fuerza bruta.

Uso de OAuth 2.0 y JSON Web Tokens (JWT)

OAuth 2.0 es un protocolo que permite a un usuario dar acceso a su información a un sitio web o una aplicación de terceros sin compartir sus credenciales. Se utiliza ampliamente por su escalabilidad y simplicidad.

En el contexto de la autenticación, JSON Web Tokens (JWT) es un mecanismo popular que se utiliza para intercambiar información de forma segura entre partes mediante un objeto JSON. La información incluida en un JWT se puede verificar y considerar confiable porque está firmada digitalmente.

Este es un ejemplo de cómo usar JWT para la autenticación en una API REST de Node.js:

const jwt = require("jsonwebtoken");

// User login
app.post("/login", (req, res) => {
  // Authenticate user
  // ...

  // Generate JWT
  const token = jwt.sign({ userID: user.id }, "your-secret-key");

  // Return token
  res.json({ token });
});

// Secure endpoint
app.get("/secure", (req, res) => {
  // Get token from headers
  const token = req.headers["x-access-token"];

  // Verify token
  jwt.verify(token, "your-secret-key", (err, decoded) => {
    if (err) {
      return res.sendStatus(403);
    }

    // Access granted
    // ...
  });
});

Prácticas recomendadas para administrar tokens de acceso

Los tokens de acceso son las llaves de tu API y deben administrarse de forma segura. Estas son algunas prácticas recomendadas:

  • Vencimiento de los tokens: Los tokens de acceso deben tener una vida útil breve. Así se reduce el impacto si un token se ve comprometido.

  • Almacenamiento de los tokens: Evita almacenar tokens de acceso en el almacenamiento local, ya que los atacantes pueden acceder a ellos fácilmente si la aplicación es vulnerable a secuencias de comandos entre sitios (XSS). En su lugar, usa mecanismos de almacenamiento seguros, como cookies HTTP-only con propiedades de seguridad habilitadas (same site, indicador secure y HTTP-only, entre otras prácticas recomendadas).

  • Transmisión de los tokens: Transmite siempre los tokens por canales seguros. Usa HTTPS en lugar de HTTP para evitar ataques de intermediario.

Snyk Open Source puede ayudarte a detectar vulnerabilidades en las dependencias de código abierto que usas para administrar tokens. Así te aseguras de que tus tokens de acceso estén administrados por una biblioteca que no tenga vulnerabilidades de seguridad conocidas. Para obtener más información sobre la seguridad de las aplicaciones y anticiparte a las amenazas, crea una cuenta gratuita de Snyk.

2. Protege los datos en tránsito y en reposo

Proteger los datos, tanto en tránsito como en reposo, es un aspecto fundamental de la seguridad de una API REST. En esta sección encontrarás prácticas recomendadas para proteger los datos en tránsito y en reposo.

HTTPS (Protocolo seguro de transferencia de hipertexto) es una medida de seguridad esencial para cualquier API. Garantiza que los datos transferidos entre el cliente y el servidor estén cifrados y que los atacantes no puedan interceptarlos.

La mayoría de los proveedores de servicios en la nube y de infraestructura de hosting te ofrecen un certificado SSL gratuito, que puedes usar para habilitar HTTPS en tu API REST. Sin embargo, si necesitas realizar la terminación SSL en el código de tu propia aplicación para la comunicación entre microservicios internos o por otros motivos, aquí tienes un ejemplo de cómo exigir HTTPS en una aplicación Flask mediante la extensión Flask-SSLify del paquete de Python:

from flask import Flask, request
from flask_sslify import SSLify

app = Flask(__name__)
sslify = SSLify(app)

@app.route('/')
def index():
    return "Hello, World!"

if __name__ == '__main__':
    app.run()

En el fragmento de código Python anterior, usamos la extensión Flask-SSLify para exigir HTTPS en una aplicación Flask. Esta es una de las formas de proteger tu API REST con HTTPS.

Métodos de cifrado de datos

El cifrado de datos es otro aspecto fundamental de la seguridad de una API REST. Garantiza que, aunque un atacante logre acceder a tus datos, no pueda leerlos sin la clave de descifrado.

Un método popular para cifrar datos es AES (Estándar de cifrado avanzado). AES es un algoritmo de cifrado simétrico ampliamente utilizado por su seguridad y eficiencia.

from Crypto.Cipher import AES
from Crypto.Random import get_random_bytes

key = get_random_bytes(16)
cipher = AES.new(key, AES.MODE_GCM)
plaintext = b'This is a test.'
ciphertext = cipher.encrypt(plaintext)

print('Ciphertext:', ciphertext)

En el fragmento de código Python anterior, usamos la biblioteca PyCryptoDome para cifrar datos con AES, una clave de 128 bits y el modo de operación GCM (modo Galois/contador).

Aprovecha los encabezados HTTP para reforzar la seguridad

Los encabezados HTTP pueden reforzar la seguridad de tu API REST. Encabezados como Content Security Policy (CSP) y X-Content-Type-Options pueden ayudar a prevenir vulnerabilidades web comunes.

CSP es un encabezado de seguridad que ayuda a prevenir ataques de secuencias de comandos entre sitios (XSS) al controlar los recursos que una página web puede cargar.

X-Content-Type-Options es otro encabezado de seguridad que evita la detección automática del tipo MIME, una técnica que los atacantes utilizan para engañar al navegador y lograr que ejecute secuencias de comandos maliciosas.

@app.after_request
def apply_caching(response):
    response.headers["X-Content-Type-Options"] = "nosniff"
    response.headers["Content-Security-Policy"] = "default-src 'self'"
    return response

En el fragmento de código Python anterior, configuramos los encabezados X-Content-Type-Options y CSP en una aplicación Flask.

Te recomiendo leer cómo una Content Security Policy puede prevenir XSS y otras vulnerabilidades.

3. Valida y depura los datos de entrada

Uno de los pasos más importantes para proteger una API REST es validar y depurar los datos de entrada. Este paso es fundamental para prevenir ataques como la inyección SQL.

La inyección SQL es una amenaza de seguridad común que aprovecha vulnerabilidades en los campos de entrada de datos de una aplicación. En este tipo de ataque, un atacante puede manipular consultas SQL mediante la inserción de código SQL malicioso en los campos de entrada de la aplicación, lo que le permite acceder a datos sin autorización o manipularlos. De forma similar, los ataques de inyección NoSQL pueden ocurrir cuando un atacante manipula una consulta a una base de datos NoSQL al insertar código malicioso en los campos de entrada de la aplicación.

El equipo de investigación de seguridad de Snyk publicó anteriormente avisos de seguridad que revelaron que la popular biblioteca ORM Sequelize era vulnerable a ataques de inyección SQL. Esto pone aún más de relieve la importancia de validar y depurar los datos de entrada, así como de monitorear las vulnerabilidades de tus bibliotecas de código abierto (puedes usar Snyk Open Source gratis para ayudarte con esto).

Implementación de técnicas de validación de entradas

Para mitigar estos riesgos, es fundamental implementar técnicas de validación de entradas. La validación garantiza que solo los datos con el formato correcto ingresen a tu sistema. Por ejemplo, si se espera que la edad de un usuario sea un número, el sistema debe rechazar cualquier entrada que no lo sea.

Este es un ejemplo sencillo de validación de entradas en JavaScript:

function validateAge(age) {
  if (isNaN(age)) {
    throw new Error("Invalid input: age must be a number");
  }
}

Mejor aún, puedes usar una biblioteca como Zod o Joi para validar las entradas de forma más sólida y fácil de mantener. Estas bibliotecas definen un esquema esperado para tus datos de entrada y los validan según ese esquema. Son más rápidas y confiables que escribir tu propia lógica de validación. Si te gusta TypeScript, Zod es una excelente opción, ya que está diseñada para trabajar con TypeScript.

Además de validar las entradas, también debes depurar los datos para neutralizar cualquier posible efecto perjudicial de las entradas maliciosas. La depuración de datos elimina o modifica los datos para impedir que se usen de formas dañinas.

Este es un ejemplo sencillo de depuración de datos en JavaScript:

function sanitizeString(str) {
  return str.replace(/<[^>]*>?/gm, "");
}

Sin embargo, no te excedas con la depuración mediante RegEx. No es una solución infalible y los atacantes pueden eludirla. En su lugar, usa bibliotecas de utilidades como validator.js, disponible en el ecosistema de npm, que ofrece una amplia variedad de métodos de validación para distintos tipos de datos. Al escribir una RegEx, es probable que no tengas en cuenta algunos casos límite y que introduzcas una vulnerabilidad de seguridad conocida como denegación de servicio por expresiones regulares (ReDoS). Snyk publicó anteriormente un análisis detallado sobre la vulnerabilidad ReDoS de UAParser.js, una biblioteca popular.

Validar y depurar manualmente cada fragmento de datos puede ser tedioso. Por suerte, hay herramientas que pueden automatizar estas tareas. Una de ellas es Snyk Code. Snyk Code es una solución de pruebas de seguridad de aplicaciones estáticas (SAST) que puede ayudarte a identificar y corregir vulnerabilidades en tu código, incluidas las relacionadas con la validación y depuración de entradas.

4. Usa dependencias seguras

Al pensar en cómo proteger una API REST, es fundamental prestar atención a las dependencias de las que depende tu aplicación. En secciones anteriores, mencionamos varias bibliotecas y frameworks populares que se han identificado como vulnerables a amenazas de seguridad.

En esta sección, destacaremos los posibles peligros de usar bibliotecas vulnerables, cómo aprovechar Snyk Open Source para detectar estas vulnerabilidades y qué estrategias puedes seguir para mantener tus dependencias actualizadas.

El peligro de usar bibliotecas vulnerables

Las dependencias son como los bloques de construcción de tu aplicación. Sin embargo, así como un ladrillo débil puede comprometer la integridad de un edificio, una biblioteca vulnerable puede representar graves riesgos de seguridad para tu API REST.

Por ejemplo, la famosa filtración de datos de Equifax de 2017 se atribuyó a una vulnerabilidad en Apache Struts, un framework de código abierto para crear aplicaciones web Java. La filtración expuso los datos personales de 147 millones de personas y puso de relieve la importancia fundamental de usar dependencias seguras.

// Example of a vulnerable Apache Struts configuration
<struts>
  <constant name="struts.devMode" value="true" />
</struts>

En el ejemplo anterior, struts.devMode está configurado como true, lo que puede exponer información confidencial y debe evitarse en un entorno de producción.

El modo de desarrollo (devMode) de Apache Struts está pensado para tareas de desarrollo y depuración. Cuando devMode está habilitado, el framework ofrece registros más detallados, informes de errores y funciones para volver a cargar la configuración. Estas funciones son útiles durante el desarrollo, pero pueden exponer información confidencial y abrir posibles vulnerabilidades de seguridad si se habilitan en un entorno de producción.

Por ejemplo, habilitar devMode puede provocar lo siguiente:

  • Se muestran mensajes de error detallados a los usuarios, lo que puede revelar información sobre la estructura de la aplicación, la tecnología subyacente e incluso líneas de código y rutas específicas que se pueden explotar.

  • La configuración se vuelve a cargar automáticamente, lo que puede aprovecharse para alterar el comportamiento de la aplicación sin necesidad de reiniciarla.

  • Aumenta el uso de recursos debido al registro y procesamiento adicionales, lo que podría afectar el rendimiento y la estabilidad.

Por lo tanto, una práctica recomendada de seguridad es asegurarse de que devMode esté configurado como false en los entornos de producción para mitigar estos riesgos.

Usa Snyk Open Source para detectar dependencias vulnerables

Para mitigar el riesgo de usar bibliotecas vulnerables, es fundamental contar con un sistema sólido para detectar y gestionar estas vulnerabilidades. Aquí es donde entra en juego Snyk Open Source.

Snyk Open Source es una herramienta que te ayuda a identificar y corregir vulnerabilidades en tus dependencias de código abierto. Ofrece una base de datos integral de vulnerabilidades conocidas y supervisa continuamente tus dependencias para alertarte sobre cualquier riesgo nuevo.

# Example of using Snyk Open Source to scan your project for vulnerabilities
snyk test

En el ejemplo anterior, el comando snyk test analiza tu proyecto en busca de vulnerabilidades y ofrece recomendaciones prácticas para corregirlas. Los resultados del análisis se muestran en tu terminal (o en el panel de Snyk si usas la interfaz web de Snyk) e incluyen detalles sobre las vulnerabilidades, su gravedad y las correcciones sugeridas. Este es un ejemplo de los resultados para una aplicación Java con Spring que usa una versión vulnerable de Apache Struts:

Testing /path/to/your/project...

✗ High severity vulnerability found in org.apache.struts:struts2-core@2.3.20
  Description: Remote Code Execution
  Info: https://snyk.io/vuln/SNYK-JAVA-ORGAPACHESTRUTS-31560
  Introduced through: org.apache.struts:struts2-core@2.3.20
  From: org.apache.struts:struts2-core@2.3.20 > org.apache.struts:struts2-core@2.3.20
  Remediation:
    Upgrade direct dependency org.apache.struts:struts2-core@2.3.20 to org.apache.struts:struts2-core@2.3.24

Tested 123 dependencies for known vulnerabilities, found 1 vulnerabilities, 1 vulnerable paths.

Estrategias para mantener tus dependencias actualizadas

Mantener tus dependencias actualizadas es fundamental para proteger tu API REST. Estas son algunas estrategias que te ayudarán a gestionarlas de manera eficaz:

  1. Busca actualizaciones con regularidad: Acostúmbrate a buscar actualizaciones de tus dependencias periódicamente. Puedes hacerlo de forma manual o con herramientas como Snyk, que automatizan el proceso.

  2. Usa una estrategia de control de versiones: Adopta una estrategia de control de versiones que equilibre la necesidad de contar con las funciones más recientes y la estabilidad de tu aplicación. El versionado semántico es un enfoque popular que usa números de versión para comunicar el tipo y el alcance de los cambios.

  3. Automatiza las actualizaciones cuando sea posible: Automatizar las actualizaciones de dependencias puede ahorrarte mucho tiempo y reducir el riesgo de errores humanos. Puedes configurar Snyk para que abra automáticamente pull requests con actualizaciones y parches seguros.

# Example of using Snyk to automate dependency updates
snyk monitor

En el ejemplo anterior, el comando snyk monitor supervisa continuamente tu proyecto y abre automáticamente pull requests con actualizaciones y parches seguros. Si sigues estas prácticas recomendadas, puedes asegurarte de que tus dependencias no se conviertan en el eslabón débil de la seguridad de tu API REST. Recuerda que, cuando se trata de «cómo proteger una API REST», cada detalle importa y las dependencias seguras son una pieza fundamental.

Recuerda que proteger tu API REST implica mucho más que validar y sanitizar los datos de entrada. Es un proceso continuo que requiere supervisión y actualizaciones periódicas. Si sigues estas prácticas recomendadas y usas herramientas como Snyk, puedes mejorar significativamente la seguridad de tu API REST.

¿Todo listo para empezar a proteger tu API REST? Regístrate en Snyk hoy mismo.

Leer más

Blog

Los modelos de frontera encontraron las vulnerabilidades. Solo el atacante encontró las cadenas.

El análisis estático encontró las fallas, pero solo las pruebas de ataque en vivo demostraron cómo podían encadenarse para provocar brechas. Una comparación de Evo COS, Claude Security y Claude Code Security.

feature insights context
Blog

Los ataques autónomos ya están aquí. La defensa debe estar a su altura.

Los atacantes autónomos están reduciendo el tiempo disponible para defenderse. Descubre cómo el descubrimiento, la corrección, la validación y la prevención continuos pueden ayudar a los equipos de seguridad a seguirles el ritmo.

Blog

Por qué los agentes de programación con IA siguen generando fallas de control de acceso

Los agentes de programación con IA pueden generar lógica de autorización que compila y supera la revisión, pero expone los datos de un inquilino a otro. Descubre por qué es difícil detectar el control de acceso roto y cómo prevenirlo.