Deuda de seguridad, o cuando los bichos van mal
De vez en cuando, el mundo de las TI se ve afectado por un resurgimiento de la preocupación, a veces una tendencia pasajera, otras veces un problema importante. Últimamente, el término "deuda de seguridad" ha estado circulando por las plataformas de noticias de TI. Este artículo pretende desentrañar la esencia de la deuda de seguridad y sus implicaciones.
De la deuda técnica a la deuda de seguridad
El concepto de "deuda técnica" es familiar para muchos; se refiere a los retos que surgen cuando los proyectos se expanden más allá de proporciones manejables. Este "tamaño" puede medirse en líneas de código, módulos, funciones u otras métricas, que reflejan la capacidad de un equipo para añadir simultáneamente nuevas características y mantener el código existente.
Por ejemplo, es órdenes de magnitud más difícil añadir nuevas funcionalidades a una aplicación madura que a esa misma aplicación cuando el desarrollo apenas está empezando. Hay menos partes móviles y menos interacciones entre las distintas partes del código, lo que hace que añadir nuevas funcionalidades tenga menos probabilidades de romper las existentes. A medida que la aplicación evoluciona, cada cambio puede provocar una interacción inesperada en alguna otra parte del código. Eso significa "has añadido un error" en la jerga de los desarrolladores. Enfrentados a un tiempo y unos recursos limitados, los desarrolladores deben compaginar el nuevo desarrollo con la corrección de errores, lo que ralentiza el progreso general. Este retraso en el mantenimiento constituye la "deuda técnica".
Algunos - si no todos - de esos errores, cuando se dejan en el código durante el tiempo suficiente, pueden convertirse en problemas de seguridad. Por ejemplo, una variable desbordada, o subdesbordada, en algún lugar puede significar simplemente que un informe obtenga un valor erróneo, o, si alguien encuentra una manera de activarlo, puede conducir a la corrupción de memoria en partes no relacionadas de la aplicación. Esta es la "deuda de seguridad", es decir, los fallos de seguridad que están en el código, a veces durante meses o incluso años, hasta que alguien se pone a solucionarlos. Si se dejan desatendidas, estas vulnerabilidades pueden explotarse antes de que se rectifiquen.
¿Por qué está volviendo?
El principal culpable es la complejidad. Las bases de código son cada vez mayores. Siempre se añaden nuevas funciones al software, nunca al revés. Eso significa que se añade más código, no que se elimina. Nuestros cerebros humanos luchan por comprender plenamente las complejidades de nuestras creaciones digitales.
Pensemos en la base de código del núcleo de Linux, que pasó de 2,4 millones de líneas de código en 2001 a más de 20 millones en 2015. Nadie, ni ningún equipo, es capaz de comprender adecuadamente todos sus aspectos. Así que cada vez que alguien añade una nueva línea de código, puede funcionar bien o puede provocar un colapso en otro lugar. Lanzar una moneda al aire daría las mismas posibilidades.
Esto no es exclusivo del Kernel, ni siquiera de proyectos de esta magnitud, ni siquiera de proyectos de código abierto. Este aumento de la complejidad ocurre igualmente en el software propietario de código cerrado, simplemente no disponemos de métricas del tamaño del código que lo demuestren. Si nos fijamos en los tamaños binarios para comparar, Windows 95 se distribuyó en 13 disquetes de 1,68 MB (no es una errata, esos disquetes utilizaban una disposición diferente de las pistas para que cupieran más datos, y tenían un doble propósito como mecanismo de protección anticopia). Windows 11 se envía en una iso de aproximadamente 5 GB.
Así que sí, la base de código aumentó.
Tampoco es porque los desarrolladores hayan empeorado de repente. El desarrollador típico puede ser capaz de entender con precisión unas pocas docenas de líneas de código de memoria. Un buen desarrollador puede ser el doble o el triple (estoy siendo intencionadamente impreciso, ya que esto es difícil de evaluar). esto es difícil de calibrar). Para todos, mirar código que no han visto en unos días o semanas es como leer un idioma extranjero por primera vezy el cambio de contexto lleva su tiempo.
Entender proyectos enteros ya no es una perspectiva esperada. El hecho de que codifiquemos errores es un claro recordatorio de ello.
¿Eso es todo?
El problema se agrava por la "complejidad oculta", que se introduce con cada biblioteca o componente de terceros que se añade. Un informe reciente destacaba que el proyecto Java medio tenía aproximadamente 150 dependenciasun aumento significativo con respecto al año anterior. Esta complejidad se suma a la ya difícil tarea de gestionar el código de terceros.
Hacer frente a la deuda de seguridad
Todo este código incluye intrínsecamente errores, muchos de los cuales son directamente problemas de seguridad. Tratarlos correcta y oportunamente es difícil. La dificultad depende de varios factores:
- La rapidez con que se detectanlo que a su vez depende de las pruebas que se realicen en el proceso de desarrollo y compilación: Si las comprobaciones de seguridad se realizan al final de una larga ventana de fusión en la que varios desarrolladores envían código durante un largo periodo de tiempo, cuando se activan las alertas, el esfuerzo del desarrollador original para solucionar el problema es mucho mayor, ya que no podrá recordar la razón por la que algo se implementó de la forma en que se hizo.
- Cómo de exhaustivas son sus pruebas: ¿Sólo busca problemas específicos? Puede que el análisis estático sólo busque patrones concretos, como variables mal tipadas, desbordamientos de búfer o uso de NULL. Algo más puede pasar desapercibido hasta que se encuentra en la naturaleza.
- El número total de problemas identificados: Si tiene que resolver un gran número de problemas de seguridad, ¿dispone de los recursos necesarios (tiempo, conocimientos, personal) para solucionarlos todos? ¿Está estableciendo prioridades? ¿Qué pasa si ocurre algo que hace que un problema de baja prioridad pase a ser más importante? ¿Es su sistema lo bastante flexible para reaccionar?
La deuda de seguridad tiene muchos aspectos, y este artículo sólo aborda algunos de los principales. Su objetivo era hacer sonar una alarma sobre el problema de la deuda técnica que se convierte en deuda de seguridad cuando la complejidad crece más allá de la capacidad de un desarrollador o equipo para gestionarla adecuadamente.
Existen algunas tácticas para abordar el problema: mejores pruebas de seguridad, pruebas de seguridad más tempranas, pruebas de seguridad antes de confirmar el código (en lugar de comprobarlo después de que todo el mundo lo haya confirmado), revisión por pares, externalizar las comprobaciones de las bibliotecas de terceroso incluso contratar a más desarrolladores a medida que crecen las bases de código. Por sí solas, ninguna de estas sugerencias resolverá el problema por completo, pero juntas podrían mantener a raya la complejidad durante más tiempo y mitigar su impacto.
Nota: Si quieres saber más sobre el problema, el podcast "Enterprise Linux Security" tiene un episodio, el 84, sobre el tema. Puede encontrarlo en todas las plataformas de podcast o en YouTube con una sesión de grabación en directo.