Identificar código C inseguro con Valgrind y corregirlo con Snyk Code
24 de septiembre de 2024
0 minutos de lecturaC y C++ siguen siendo fundamentales para el desarrollo de software crítico. Estos lenguajes impulsan una amplia variedad de sistemas, desde dispositivos integrados hasta aplicaciones de alto rendimiento en la industria manufacturera, la tecnología operativa (OT) y el sector industrial. Su eficiencia, el control que ofrecen sobre los recursos del sistema y su rendimiento los hacen indispensables para los desarrolladores que trabajan en proyectos de misión crítica.
C y C++ son especialmente comunes en Japón, donde los sectores manufacturero e industrial son motores económicos clave. Los desarrolladores japoneses confían en estos lenguajes para crear software sólido y eficiente, que sustenta desde los sistemas automotrices hasta la automatización de fábricas. La precisión y confiabilidad de C y C++ son cruciales para mantener los altos estándares que se esperan en estas industrias.
La importancia de la seguridad del código en C y C++
Aunque C y C++ ofrecen un control y un rendimiento incomparables, también plantean importantes desafíos de seguridad. La falta de funciones de seguridad integradas, como la administración automática de memoria, hace que estos lenguajes sean propensos a vulnerabilidades como los desbordamientos de búfer, el uso después de liberar memoria y las fugas de memoria. Aunque parezcan ingenuas y básicas, estas vulnerabilidades pueden tener consecuencias graves, especialmente en software crítico, donde la confiabilidad y la seguridad son primordiales.
El código C vulnerable provoca una fuga de memoria
Veamos un ejemplo de código C vulnerable que los desarrolladores podrían escribir y que introduce una vulnerabilidad de seguridad relacionada con las fugas de memoria.
Este es el código de nuestro programa en C. ¿Puedes encontrar aquí la vulnerabilidad de seguridad?
Este archivo program1.c contiene un ejemplo de vulnerabilidad de asignación dinámica de memoria (MISRA Dir 4.12, MISRA Rule 21.3). La vulnerabilidad de seguridad de la función allocateMemory() consiste en que usa malloc() para asignar memoria, pero no la libera, lo que provoca una fuga de memoria. Esto se puede evitar siguiendo las pautas de MISRA, que restringen la asignación dinámica de memoria.
Este es un error común al programar en C, que puede hacer que tu programa use cada vez más memoria. Con el tiempo, esto puede hacer que se quede sin memoria y se bloquee, o que otros programas de tu sistema se queden sin memoria.
¿Por qué no podemos usar simplemente la asignación estática de memoria, como int arr[10]? Porque, en algunas situaciones, no puedes asignar memoria en la pila. Por ejemplo, supongamos que estás escribiendo una función para leer un archivo en la memoria. No conoces el tamaño del archivo hasta que se ejecuta el programa, así que no puedes usar un arreglo de tamaño fijo. En su lugar, puedes usar malloc para asignar la cantidad exacta de memoria una vez que conozcas el tamaño del archivo.
Primero, compila el programa y luego ejecútalo:
¿El programa tiene una fuga de memoria? ¿Cómo puedes corregirla?
Encuentra la vulnerabilidad de seguridad en C con Valgrind
Valgrind es una herramienta eficaz para encontrar fugas de memoria en tu programa. Podemos ejecutarlo con Valgrind para comprobar si hay fugas de memoria.
Instala Valgrind en tu sistema. Si usas un sistema basado en Linux, puedes instalarlo con el administrador de paquetes. Este es un ejemplo para Debian:
Nota: Si usas macOS con chips basados en ARM, Valgrind no está disponible, así que omitiremos ese paso y ejecutaremos Valgrind dentro de un contenedor de Docker:
Luego, ejecuta el contenedor y asigna nuestro directorio actual al directorio /tmp del contenedor:
Luego, compila el programa program1.c dentro del contenedor:
Después, podemos ejecutar el programa con Valgrind para comprobar si hay fugas de memoria:
A continuación, deberías ver el resultado de Valgrind que muestra la fuga de memoria:
Valgrind es una excelente herramienta, pero para quienes desarrollan en C a diario, este flujo de trabajo no es escalable y requiere compilar y crear un programa completo para analizarlo.
Snyk Code te ayudará a identificar esta vulnerabilidad en tu base de código sin siquiera tener que compilar. Solo tienes que instalar la extensión y abrir el archivo para que se muestre la vulnerabilidad. Esto es posible porque Snyk Code es una herramienta de análisis estático de código que aplica técnicas de aprendizaje automático para identificar código estático, sin necesidad de compilar ni de un paso de compilación. Este enfoque permite obtener resultados confiables, con pocos falsos positivos y rápidamente, cuando Snyk analiza tu código en busca de vulnerabilidades de seguridad.

Detectar el recorrido de rutas, el desbordamiento de búfer y otras vulnerabilidades en C
El motor SAST que impulsa Snyk Code puede detectar más tipos de vulnerabilidades que las fugas de memoria causadas por malloc.
Veamos un ejemplo más complejo que combina varias prácticas de codificación inseguras en C que introducen vulnerabilidades de seguridad:
El programa en C del ejemplo anterior está repleto de vulnerabilidades, pero es una forma muy concisa e ingenua de presentar código inseguro por motivos de brevedad. Aun así, algunas prácticas de codificación sutiles podrían aparecer fácilmente en bases de código reales.
Una vez compilado el programa, puedes ejecutarlo:
Si tienes un archivo llamado text.txt en el mismo directorio y no está vacío, el programa lo leerá e imprimirá su contenido.
Por ejemplo:
Parece estar bien. ¿Qué pasa si le pasas un archivo que recorre la estructura de directorios?
El programa tiene una vulnerabilidad de recorrido de rutas, que permite a un atacante leer archivos confidenciales del sistema.
Para probar otras vulnerabilidades, intenta:
Pasar un archivo que no existe
Pasar un archivo vacío
Pasar un nombre de archivo o una ruta completa demasiado largos (más de 50 caracteres)
Algunos de estos problemas de seguridad van mucho más allá de las habilidades de programación en C de un desarrollador. Por ejemplo, el recorrido de rutas requiere conocer la seguridad de las aplicaciones, además de saber administrar la memoria de forma segura y contar con experiencia consolidada en el desarrollo con C.
Por suerte, cuando pegas el código del programa en el IDE, la extensión de Snyk analiza el código C en busca de convenciones de codificación inseguras y problemas comunes de seguridad de las aplicaciones. Los reporta rápidamente y muestra el contexto directamente en el código:

Protege tu código C y C++ con Snyk
Una brecha de seguridad en los sectores manufacturero e industrial puede tener consecuencias catastróficas, como interrupciones operativas, riesgos para la seguridad y pérdidas financieras. Garantizar la seguridad del código en C y C++ no es solo una buena práctica: es una necesidad. Snyk ofrece a los desarrolladores las herramientas para identificar y corregir vulnerabilidades desde las primeras etapas del proceso de desarrollo.
Protege tu código con información de vanguardia
Conoce todas las funcionalidades de SAST de Snyk Code en solo 30 minutos.
