Bestiario de una memoria mal gestionada (IV)David García 18 mayo, 2020 Si tuviéramos que elegir una vulnerabilidad especialmente dañina sería, con mucha probabilidad, la ejecución de código arbitrario, y más aún si puede ser explotada en remoto. En la primera entrada introdujimos los problemas que puede acarrear una memoria mal gestionada, en la segunda hablamos del double free y en la tercera abordamos los punteros colgantes y las fugas de memoria. Terminamos esta serie con el uso de memoria no inicializada y las conclusiones. Uso de memoria no inicializada Por eficiencia, cuando llamamos a “malloc” o utilizamos el operador “new” en C++, la zona de memoria que nos asignan no está inicializada. ¿Qué quiere decir esto? Que no contiene un valor por defecto, sino datos que nos parecerán aleatorios y que no tienen sentido en el contexto de nuestro proceso. Veamos: Obtenemos un fragmento de 10.000 enteros, lo llenamos de enteros aleatorios y lo liberamos. En teoría, según el estándar de la librería C, la memoria que proviene de ‘malloc’ no debería estar inicializada, pero en determinados sistemas (sobre todo modernos) es probable que venga inicializada a cero. Esto es, toda la zona reservada está llena de ceros. En el programa, hacemos uso de una zona de memoria reservada y, a continuación, la liberamos. Pero cuando volvemos a hacer uso de este tipo de memoria, el sistema nos devuelve ese mismo fragmento con el contenido que ya poseía. Este contenido probablemente no tenga sentido en el contexto de ejecución actual. Observemos la salida: ¿Qué ocurriría si utilizamos esos datos de forma accidental? Vamos a verlo, de nuevo, con código. Modificamos el programa para que la segunda reserva se haga para una estructura que hemos definido: Como vemos, hacemos uso en ‘p’ llenando esa zona de datos aleatorios. Liberamos ese fragmento y ahora reclamamos uno para una estructura que debería contener un puntero a una cadena y dos valores enteros. Veamos una serie de ejecuciones: Como vemos, la estructura se inicializa con “basura” y hacer uso de esta «basura» es problemático, cuando no preocupante, y completamente inseguro. Imaginad que esos valores son usados para una aplicación crítica. Además de los ya mencionados, los problemas de gestión manual de memoria no acaban aquí. Lo que hemos visto ha sido sólo una pequeña muestra y la lista sería interminable: aritmética de punteros, escritura fuera de límites, etc. Los nuevos mecanismos de gestión C++ ha mejorado mucho la gestión manual de forma que si ya en los primeros pasos del lenguaje se eliminó la necesidad de usar funciones a través de operadores («new» y «delete»), el nuevo estándar amplía y mejora la gestión de memoria a través de punteros “inteligentes”. Es decir, contenedores de memoria que invocan su propio destructor cuando detectan que ya no son útiles. Por ejemplo, cuando un objeto sale de un ámbito y ya no es referenciado por ninguna otra variable u objeto. Aun así, incluso con punteros inteligentes, queda espacio para la sorpresa e incluso para casos en los que tenemos que hacer uso del método tradicional, ya sea por eficiencia o por limitación en las librerías usadas por una aplicación. Otro método de gestión de memoria que no precisa de recolector es el sistema usado por lenguajes como Swift o Rust. El primero usa un tipo de recolector de memoria “inmediato” que no precisa de pausas, ARC o Automatic Reference Counting. Se trata de un método que se apoya en el compilador para insertar en el código las instrucciones adecuadas para liberar memoria cuando ésta ya no va a ser usada. Rust, un lenguaje relativamente moderno, utiliza un método basado en los conceptos de “préstamos” y “propiedad” de los objetos creados con memoria dinámica. Un compromiso intermedio entre no tener que llevar la mochila de un recolector de memoria y la molestia de que el programador se deba preocupar mínimamente en la lógica de “prestar” un objeto a otros métodos. Conclusiones Está claro que el manejo de la memoria de forma manual causa un tremendo vórtice de problemas que pueden (y normalmente lo hacen) derivar en serios problemas de seguridad. Por otro lado, se requiere una buena capacidad, atención y experiencia en los programadores que usan lenguajes como C o C++. Esto no quiere decir que se deba abandonar este tipo de lenguajes por resultar complejo su uso en ciertos aspectos. Como ya dijimos al principio, no se puede evitar su uso en cierto tipo de aplicaciones. No te pierdas las anteriores entradas de este post: Bestiario de una memoria mal gestionada (I) Bestiario de una memoria mal gestionada (II) Bestiario de una memoria mal gestionada (III) La industria retail farmacéutica y sus aplicaciones móvilesElevenPaths Radio 2×08 – Entrevista a Manuel Bruscas
Telefónica Tech Qué es el Esquema Nacional de Seguridad (ENS 2.0) La Ciberseguridad, la privacidad y la protección de los datos y de la información sensible son aspectos cada vez más importantes en la sociedad actual. Tanto para empresas y...
Nacho Palou 5G: cuatro casos de uso reales y prácticos El último informe “La Sociedad Digital en España 2022” [1] de Fundación Telefónica confirma la consolidación de los procesos de digitalización en la sociedad española. En este sentido, cabe...
Susana Alwasity Ciberseguridad: eventos “cisne negro” en un mundo conectado En la sociedad actual, la tecnología ha transformado la forma en que vivimos, trabajamos y nos relacionamos. Con el aumento del uso de dispositivos y redes conectados a internet,...
Telefónica Tech Boletín semanal de Ciberseguridad, 11 – 17 de marzo Nueva versión del troyano bancario Xenomorph Investigadores de ThreatFabric han detectado una nueva variante del troyano bancario para Android Xenomorph. Esta familia de malware fue detectada por primera vez en febrero...
Gonzalo Álvarez Marañón Matemáticas contra el cibercrimen: cómo detectar fraude, manipulaciones y ataques aplicando la Ley de Benford Cómo aplicar la ley de Benford para luchar contra el cibercrimen. La respuesta, en este post que utiliza las matemáticas para ayudar a la ciberseguridad.
Javier Herrero Mi experiencia como voluntario en la iniciativa AulaCibersegura para proteger a los menores en internet La iniciativa AulaCibersegura Desde hace mucho tiempo tenía la inquietud y necesidad personal de contribuir de alguna forma real y directa al programa de voluntariado que promueve Telefónica. Antes me...