Bestiario de una memoria mal gestionada (III)David García 4 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 siguiente hablamos del double free. Ahora veremos más ejemplos. Dangling pointers o punteros colgantes La gestión manual de la memoria es compleja y se debe prestar atención al orden de las operaciones, de dónde se obtienen recursos y dónde dejamos de usarlos para poder liberarlos en buenas condiciones. También se requiere seguir la pista a copias de punteros o referencias que, si son liberadas antes de tiempo, hacen que los punteros se queden “descolgados”, o en su versión en inglés, dangling pointers. Es decir, hacer uso de un recurso que ya ha sido liberado. Un ejemplo: Ejecutamos: Esto nos deja con un puntero que está apuntando a una zona de memoria (montículo) que no es válida (observemos que no imprime nada después de “(p2) apunta a…”. Es más, no existe forma de saber si un recurso al que se ha copiado su dirección continúa siendo válido, del mismo modo que no es posible recuperar un leak de memoria si se pierde su referencia (lo veremos más adelante). Para señalizar que un puntero no es válido, asignamos la macro NULL a ese puntero (en C++ “moderno” asignaríamos nullptr) para advertir de alguna forma que no apunta a nada. Pero si ese NULL no es comprobado, no nos sirve de nada. Por tanto, por cada puntero que utilice un recurso debe comprobarse “su no NULLidad”. La buena práctica es, por lo tanto: una vez liberamos memoria, asignamos NULL o nullptr (en C++) para señalizar que ese puntero ya no apunta a nada válido. Y además, antes de hacer uso de él, tanto para copiarlo como para desreferenciarlo, comprobamos su validez. Memory leaks o fugas de memoria Justo lo contrario a hacer uso de una zona de memoria que ya no es válida es hacer que ningún puntero apunte a una zona de memoria válida. Una vez perdida la referencia, ya no podremos hacer free sobre esa reserva de memoria, y ocupará ese espacio de forma indefinida hasta que el programa termine. Esto es un gran problema si el programa no termina, como por ejemplo, un servidor que normalmente se ejecuta hasta que la máquina se apague u ocurra alguna otra interrupción ineludible. Un ejemplo (si lo queréis replicar, hacedlo en un sistema virtualizado que se tenga para experimentar): El código que se ve a la derecha va obteniendo porciones de memoria hasta agotar toda la memoria de montículo. Esto produce que el sistema vaya agotando la RAM, empiece a hacer swapping y finalmente saldrá el OOM-killer a matar el proceso por pasarse de la raya con el consumo de memoria. ¿Qué es el OOM-killer? Es un procedimiento especial del kernel (en sistemas Linux) para eliminar procesos en memoria con el objeto de que el sistema no se desestabilice. En la captura podemos ver la salida del comando ‘dmesg’ en el que se refleja el kill de nuestro proceso por el coste de recursos que le supone al sistema. Si analizamos el código vemos que entramos en un bucle infinito en el que se va reservando memoria y reasignando el mismo puntero a nuevos bloques de esa memoria. Las referencias anteriores no se liberan y se pierden, lo que produce una incesante fuga de memoria (exactamente igual a una cañería rota) que termina drásticamente. Esto es evidentemente una dramatización de lo que ocurre en un programa real, pero la realidad es que ocurre así. El problema es que no se controlan las reservas de memoria en un punto, se van acumulando referencias perdidas y termina siendo un problema. Es posible que, en aplicaciones con fugas de memoria que sólo usamos durante unas horas, tan sólo notemos una ralentización (esto era más evidente en tiempos donde la RAM era más limitada) o una acumulación de memoria. Pero en servidores es común que esto conlleve la caída del servicio. En la próxima entrada veremos el uso de memoria no inicializada. No te pierdas la serie completa de este artículo: Bestiario de una memoria mal gestionada (I) Bestiario de una memoria mal gestionada (II) Bestiario de una memoria mal gestionada (IV) Iniciativa solidaria Covid-19: recargando IFEMA de energía para los enfermosElevenPaths Radio – 2×07 Entrevista a Yaiza Rubio
Telefónica Tech Boletín semanal de Ciberseguridad, 22 – 26 de mayo GitLab parchea una vulnerabilidad crítica GitLab ha abordado una vulnerabilidad crítica que afecta a GitLab Community Edition (CE) y Enterprise Edition (EE) en la versión 16.0.0. En concreto, dicho fallo...
David García ¿Salvará Rust el mundo? (II) Segunda entrega en la que descubrimos cómo Rust, el lenguaje de programación de código abierto centrado en la seguridad, mejora el panorama en cuanto a vulnerabilidades basadas en errores...
Sergio de los Santos Cuatro hitos en Ciberseguridad que marcaron el futuro del malware Un recorrido por los 15 años que ha dedicado Microsoft para consolidar una estrategia que ha repercutido en la Ciberseguridad a nivel global
Telefónica Tech Boletín semanal de Ciberseguridad, 15 – 19 de mayo Vulnerabilidades en plataformas cloud El equipo de investigadores de Otorio descubrió 11 vulnerabilidades que afectan a diferentes proveedores de plataformas de administración de cloud. En concreto, se tratan de Sierra...
Javier Martínez Borreguero Automatización, Conectividad e Inteligencia Aumentada al servicio de una reindustrialización competitiva, disruptiva y sostenible Por segundo año consecutivo vuelvo a participar en el Advanced Factories (AF 2023), la mayor exposición y congreso profesional dedicado a la Industria 4.0 del sur de Europa. Un...
Nacho Palou Passkey es otro clavo de Google en el ataúd de las contraseñas Passkey de Google ofrece a los usuarios la posibilidad de utilizar una llave de acceso para identificarse y acceder a sitios web o apps sin teclear su nombre de...