Aikido

10 amenazas comunes de seguridad en aplicaciones web

Joel HansJoel Hans
|
#

¿Por qué estás aquí?

Sabes que tus aplicaciones son vulnerables a todo tipo de ataques. En general, se pronosticó que el cibercrimen costaría 9,5 billones de dólares en 2025, según Cybersecurity Ventures, lo que representa un aumento de tres veces respecto a 2015. Y el año pasado, los ataques a aplicaciones web representaron el 12% de todas las filtraciones de datos, frente al 9% del año anterior. Este aumento constante, junto con el hecho de que no asegurar las aplicaciones web puede violar numerosas regulaciones, significa que los desarrolladores están interesados en comprender mejor las amenazas que más les afectan. 

Así que vamos a reducir el ruido en torno a las vulnerabilidades comunes y a centrarnos en tres detalles esenciales:

  • El TL;DR, que te informará mejor sobre el tipo de ataque. 
  • Una respuesta concisa a la pregunta, “¿Esto me afecta?” con un claro sí o no (✅ o 🙅) y una breve explicación.
  • Consejos rápidos en respuesta a “¿Cómo puedo solucionarlo?” que no implican herramientas costosas o refactorizaciones caras.

1. Inyección SQL e inyección NoSQL

TL;DR: Esta vulnerabilidad clásica es posible gracias a la entrada de usuario no saneada y no validada, lo que permite a los atacantes ejecutar consultas directamente contra tu base de datos. Desde allí, pueden extraer datos, modificar registros o eliminarlos a voluntad.

¿Esto me afecta?

✅ si su aplicación interactúa con una base de datos SQL o NoSQL en algún momento. Los ataques de inyección existen desde hace décadas, y los ataques automatizados comenzarán inmediatamente a sondear sus endpoints con exploits comunes.

🙅 si no tiene contenido dinámico basado en registros de la base de datos. Esto podría deberse a que su aplicación es completamente del lado del cliente, utiliza un generador de sitios estáticos (SSG) o realiza renderizado del lado del servidor con una base de datos pero nunca acepta entradas de los usuarios.

¿Cómo lo soluciono? En primer lugar, sanee y valide todas las entradas de usuario para eliminar caracteres o cadenas no deseados. Aproveche las bibliotecas y frameworks de código abierto que permiten consultas parametrizadas, y nunca concatene la entrada del usuario en una consulta de base de datos. Si utiliza Node.js, considere nuestro motor de seguridad de código abierto Runtime, que le protege de forma autónoma contra ataques de inyección SQL/NoSQL y más.

2. cross-site scripting (XSS)

TL;DR: XSS es otro ataque de inyección que permite a un atacante enviar un script malicioso a otro, potencialmente recopilando sus credenciales de autenticación o datos confidenciales.

¿Esto me afecta?

✅ si su aplicación acepta entradas de usuario y las muestra en otro lugar como contenido dinámico.

🙅 si no acepta ninguna entrada de usuario.

¿Cómo lo soluciono? Al igual que con los ataques de inyección SQL/NoSQL, debe validar la entrada del usuario cuando incluya dicha entrada dentro del href atributo de las etiquetas de anclaje para asegurar que el protocolo no sea javascript. Tenga cuidado al usar métodos de JavaScript como innerHTML o los de React como dangerouslySetInnerHTML, que pueden ejecutar arbitrariamente cualquier código incrustado en la cadena durante la salida. Independientemente de su enfoque, sanee la salida HTML con saneadores de código abierto como DOMPurify para enviar solo HTML limpio y no ejecutable a sus usuarios.

3. Falsificación de solicitud del lado del servidor (SSRF)

En resumen: Los ataques SSRF ocurren cuando un actor malicioso abusa de su aplicación para interactuar con su red subyacente, operándola como un proxy para saltar a servicios potencialmente más vulnerables o lucrativos.

¿Esto me afecta?

✅ si tu aplicación interactúa con otro servicio o API que realiza una operación específica con datos de usuario, incluso si has utilizado listas de permitidos para restringir el tráfico solo entre puntos finales conocidos y de confianza.🙅 si eres realmente estático.

¿Cómo lo soluciono? Aunque una expresión regular (regex) para validar direcciones IP o nombres de host es un buen comienzo, suele ser propensa a bypasses como la codificación octal. Dos soluciones más fiables son usar una lista blanca (allowlist) y el analizador de URL nativo de su plataforma para restringir la entrada solo a hosts seguros y conocidos, y deshabilitar las redirecciones en las solicitudes fetch. Dependiendo de su framework, también puede aprovechar libremente proyectos de código abierto —como ssrf-req-filter para Node.js— para rechazar correctamente cualquier solicitud a hosts internos.

4. Recorrido de rutas

TL;DR: Esta falla de seguridad permite a los atacantes acceder a archivos y directorios en tu servidor web haciendo referencia a archivos usando secuencias ../ o incluso rutas absolutas. Utilizando tácticas astutas como la doble codificación, los atacantes pueden usar jerarquías de carpetas/archivos específicas del framework o nombres de archivo comunes para encontrar información valiosa.

¿Esto me afecta?

✅ Tu aplicación se ejecuta en un servidor web e incluye referencias al sistema de archivos; no hay forma de evitar esto.

¿Cómo lo soluciono? Su primer paso es eliminar cualquier archivo sensible, como los que contienen variables de entorno o secretos, del directorio raíz de su servidor web y establecer un proceso para evitar futuros errores. 

es nunca almacenar archivos sensibles, como los que contienen variables de entorno o secretos, en el directorio raíz de su servidor web. Además, no almacene estos archivos en ninguna carpeta destinada a ser de acceso público, como las carpetas /static y /public de un Next.js project. Finalmente, elimina los separadores de ruta ../ y sus variantes codificadas de la entrada del usuario.

Runtime también funciona fantásticamente bien para el recorrido de rutas (path traversal)… solo digo.

5. Inyección de entidad externa XML (XXE)

TL;DR: Los ataques XXE aprovechan una debilidad en los analizadores XML que permite que las entidades externas, referenciadas por una definición de tipo de documento (DTD), sean recuperadas y procesadas sin validación ni saneamiento. El tipo y la gravedad del ataque están limitados principalmente por las habilidades del atacante y por cualquier seguridad/permisos a nivel de sistema operativo de tu proveedor de infraestructura.

¿Esto me afecta?

✅ si procesas XML por cualquier motivo, incluidos los flujos de autenticación de inicio de sesión único (single sign-on) utilizando SAML.

🙅 si no tienes que lidiar con XML en tu aplicación.

¿Cómo lo soluciono? Deshabilita la resolución de DTD externas en tu analizador XML. Es probable que no puedas rechazar las DTD por completo, ya que es normal que algunas cargas útiles XML las contengan; simplemente no permitas que tu analizador XML haga nada con ellas.

6. Deserialización

En resumen: Los atacantes pueden enviar datos maliciosos a través de una función de deserialización integrada en tu aplicación (como unserialize() de node-serialize) para ejecutar código de forma remota, realizar un ataque de denegación de servicio o incluso crear un shell inverso.

¿Esto me afecta?

✅ si tu aplicación deserializa datos directamente de la interacción del usuario o a través de funciones/servicios en segundo plano como cookies, formularios HTML, APIs de terceros, almacenamiento en caché y más.

🙅 si ejecutas una aplicación completamente estática sin nada de lo anterior.

¿Cómo lo soluciono? En general, evita deserializar datos de entrada de usuario (también conocidos como no confiables). Si es imprescindible, solo acepta dichos datos de usuarios autenticados y autorizados basándote en firmas de confianza, certificados y proveedores de identidad.

7. Inyección de shell/inyección de comandos

TL;DR: Tu aplicación pasa la entrada del usuario directamente al shell subyacente del sistema operativo en el que se ejecutan tu servidor web y tu aplicación, permitiendo a los atacantes ejecutar comandos arbitrarios o recorrer el sistema de archivos, a menudo con privilegios suficientes para extraer datos o pivotar a otro sistema.

¿Esto me afecta?

✅ si tu aplicación interactúa directamente con el sistema de archivos o el shell, como un comando UNIX tipo cat.

🙅 si ya utilizas una API o método de un framework para pasar argumentos de forma segura al comando que necesitas ejecutar, o no necesitas interactuar con el sistema de archivos/shell, como en un SSG.

¿Cómo lo soluciono? Evita aceptar la entrada del usuario directamente en los comandos o llamarlos directamente. En su lugar, utiliza la API/método de tu framework, como child_process.execFile() en Node.js, que te permite pasar argumentos en una lista de cadenas de texto. Incluso con esa protección, ejecuta siempre tus aplicaciones con los privilegios mínimos necesarios para la lógica de negocio requerida para evitar que un atacante se “escape” del servidor web y acceda a rootcarpetas y archivos solo de root.

Y sí, volvemos para un recordatorio amistoso más de añadir Runtime a cualquier proyecto Node.js con un solo comando (npm add @aikidosec/runtime || yarn install @aikidosec/runtime) para proteger instantáneamente tu aplicación contra ataques comunes de inyección de shell/comandos.

8. Inclusión de archivo local (LFI)

TL;DR: Los ataques LFI implican engañar a tu aplicación para que exponga o ejecute archivos en el sistema donde se ejecuta tu servidor web, lo que permite a los atacantes extraer información o ejecutar código de forma remota. Mientras que la 'path traversal' solo permite a los atacantes leer archivos, los ataques LFI ejecutan esos archivos dentro de tu aplicación, abriendo la puerta a una larga lista de vulnerabilidades como la ejecución remota de código (RCE).

¿Esto me afecta?

✅ si tu aplicación utiliza la ruta a un archivo como entrada de usuario.

🙅 si tu aplicación no requiere que los usuarios proporcionen rutas para completar ninguna acción.

¿Cómo lo soluciono? Siempre sanea la entrada del usuario para evitar los métodos de path traversal mencionados anteriormente. Si debes incluir archivos en el sistema de archivos local más allá de los que se encuentran típicamente en carpetas "seguras" /public o /static carpetas, utiliza una lista de permitidos (allowlist) para los nombres y ubicaciones de los archivos que tu aplicación tiene permiso para leer y ejecutar.

9. Contaminación de prototipos

En resumen: Esta vulnerabilidad específica de JavaScript permite a un atacante manipular los objetos globales de tu aplicación utilizando __proto__. El nuevo objeto se hereda entonces en toda tu aplicación, lo que podría darles acceso a datos confidenciales o escalar aún más sus privilegios.

¿Esto me afecta?

✅ si estás utilizando JavaScript.

🙅 si estás utilizando cualquier cosa excepto JavaScript! 

¿Cómo lo soluciono? Comienza saneando las claves de la entrada del usuario utilizando listas blancas o una librería auxiliar de código abierto. Puedes ampliar tu protección utilizando Object.freeze() Object.freeze() para evitar cambios en un prototipo, o incluso utilizando la --disable-proto=delete bandera --disable-proto=delete ofrecida con Node.js.

10. Redirecciones abiertas

En resumen: En este vector común de phishing, los atacantes elaboran una URL personalizada como https://www.example.com/abc/def?&success=false&redirectURL=https://example.phishing.com para engañar a tu aplicación y redirigir a usuarios desprevenidos a un sitio web malicioso. Además, los atacantes pueden encadenar redirecciones con otras vulnerabilidades para un impacto aún mayor, lo que lleva a la toma de control de cuentas y más.

¿Esto me afecta?

✅ si tu aplicación redirige a los usuarios a otra página/vista después de completar una acción, como enviarlos a example.app/dashboard después de una autenticación exitosa.

🤦 si sigues con esa vida de generación estática.

¿Cómo lo soluciono? Primero, elimina las redirecciones basadas en parámetros de tu aplicación y reemplázalas con redirecciones fijas basadas en una lista de permitidos (allowlist) de dominios y rutas de confianza a los que puedes redirigir a los usuarios después de que realicen acciones específicas. Esto podría degradar ligeramente la experiencia del usuario, pero es un compromiso significativo para proporcionar una experiencia segura, no una que les haga culparte por los gastos extraños en el extracto de su tarjeta de crédito.

¿Qué sigue?

Si te sientes abrumado por el alcance de los ataques y todo el trabajo necesario para protegerte contra ellos, debes saber que no estás solo.

Nadie espera que resuelvas todos estos problemas de seguridad y posibles vulnerabilidades por ti mismo. Los ataques de inyección SQL, por sí solos, han existido durante décadas, y la gente sigue encontrando CVEs en aplicaciones, frameworks y librerías sofisticadas todo el tiempo. Esto no quiere decir que debas tomarte estos problemas de seguridad a la ligera; si tu aplicación cumple con el ✅ para cualquiera de estos 10 principales problemas de seguridad, deberías empezar a tomar medidas.

Lo más probable es que estés utilizando herramientas de seguridad de nivel empresarial (es decir, caras y complejas), o que hayas unido un puñado de proyectos de código abierto en una pipeline de CI/CD o en 'Git commit hooks' y estés esperando lo mejor. Esto podría dejar algunas brechas de seguridad, tales como: 

  • Cómo tu aplicación podría ser vulnerable debido a prácticas de programación menos que ideales, dependencias inseguras y más allá.
  • Dónde es más probable que se oculten las vulnerabilidades, hasta líneas de código individuales (LOCs) o entradas en su package.json archivo.
  • Por qué deberías corregir ciertas vulnerabilidades de inmediato y por qué otras tienen una prioridad menor.

Aikido Security ayuda a cubrir estas brechas en 2 sencillos pasos:

1. Escanea tu código con Aikido
Regístrate (gratis, 2 min) y escanea tus repositorios. Obtén una lista focalizada de vulnerabilidades críticas basada en la arquitectura y el uso real de tu aplicación. Visualiza exactamente lo que importa, recibe correcciones guiadas y alertas sobre nuevos problemas en tus últimos commits.

2. Protege tus aplicaciones Node.js con Runtime
Añade nuestro Runtime de código abierto para bloquear ataques de inyección, contaminación de prototipos y 'path traversal' a nivel de servidor, sin la sobrecarga de WAFs o agentes. Runtime también envía datos de ataque en tiempo real a Aikido para que puedas ver qué está siendo atacado y priorizar las correcciones.

Ahora estás en el camino correcto, con una imagen más clara sobre:

  • Cómo tu aplicación es vulnerable de más formas de las que podrías haber pensado.
  • Dónde deberías enfocar tu tiempo y atención para solucionar primero los problemas más críticos.
  • Por qué el escaneo de seguridad y vulnerabilidades no es un esfuerzo puntual, sino un proceso continuo.

4.7/5

Protege tu software ahora.

Empieza gratis
Sin tarjeta
Solicitar una demo
Sus datos no se compartirán · Acceso de solo lectura · No se requiere tarjeta de crédito

Asegúrate ahora.

Proteja su código, la nube y el entorno de ejecución en un único sistema central.
Encuentre y corrija vulnerabilidades de forma rápida y automática.

No se requiere tarjeta de crédito | Resultados del escaneo en 32 segundos.