Seguridad de aplicaciones C++: top 10 vulnerabilidades y formas de protección

Entrenador de Python en Línea para Principiantes

Aprende Python fácilmente sin sobrecargarte de teoría. Resuelve tareas prácticas con verificación automática, recibe pistas y escribe código directamente en el navegador, sin instalar nada.

Start Course

Seguridad de aplicaciones C++: Top 10 vulnerabilidades y formas de protección



C++ es un potente lenguaje de programación de sistemas, pero su flexibilidad y acceso directo a la memoria hacen que las aplicaciones sean vulnerables a ataques graves. Según OWASP y CWE, muchas vulnerabilidades críticas en software industrial (desde juegos hasta aviónica) surgen precisamente debido a errores en el código C++. En este artículo, analizaremos las 10 vulnerabilidades más peligrosas, proporcionaremos ejemplos de código y mostraremos cómo evitarlas.



1. Desbordamiento de búfer (Buffer Overflow)

Vulnerabilidad clásica que permite a un atacante sobrescribir áreas de memoria adyacentes. Ocurre al copiar datos sin verificar el tamaño.



// Código vulnerable#include <cstring>void vulnerable(char* input) {    char buffer[10];    strcpy(buffer, input); // Peligro: si input tiene más de 9 caracteres}// Versión seguravoid secure(char* input, size_t len) {    char buffer[10];    if (len < sizeof(buffer)) {        strncpy(buffer, input, sizeof(buffer) - 1);        buffer[sizeof(buffer) - 1] = '\\0';    }}


Protección: use std::string, std::vector o funciones con límite de longitud (strncpy, snprintf). Active las banderas del compilador -fstack-protector-strong y -D_FORTIFY_SOURCE=2.



2. Uso después de liberación (Use-After-Free)

Acceso a memoria que ya ha sido liberada. Provoca lectura/escritura en un área ajena o la ejecución de código arbitrario.



// Código vulnerableint* ptr = new int(42);delete ptr;*ptr = 100; // ¡Error! ptr ya no es válido// Versión seguraint* ptr = new int(42);delete ptr;ptr = nullptr; // Ponemos el puntero a nuloif (ptr) *ptr = 100; // Verificación antes de usar


Protección: use punteros inteligentes (std::unique_ptr, std::shared_ptr), ponga a nulo los punteros crudos después de delete, aplique sanitizers (-fsanitize=address).



3. Desbordamiento de enteros (Integer Overflow)

Superar los límites del rango permitido en operaciones aritméticas. A menudo se usa para eludir las comprobaciones de tamaño del búfer.



// Código vulnerablesize_t size = 0;size_t user_input = 4294967295; // 2^32 - 1size_t total = size + user_input + 1; // ¡Desbordamiento!// Versión segura con verificaciónif (user_input > SIZE_MAX - size) {    throw std::overflow_error("El tamaño es demasiado grande");}size_t total = size + user_input + 1;


Protección: use tipos de ancho fijo (uint32_t), verifique el desbordamiento antes de la operación, aplique __builtin_add_overflow (GCC/Clang).



4. Desreferencia de puntero nulo (Null Pointer Dereference)

Intento de acceder a memoria en la dirección NULL. Provoca la terminación abrupta del programa (segfault) o una vulnerabilidad DoS.



// Código vulnerablevoid process(int* ptr) {    *ptr = 10; // Si ptr == nullptr — colapso}// Versión seguravoid process(int* ptr) {    if (!ptr) {        throw std::invalid_argument("Se recibió un puntero nulo");    }    *ptr = 10;}


Protección: siempre verifique los punteros con nullptr antes de usarlos, devuelva std::optional en lugar de punteros crudos.



5. Fugas de memoria (Memory Leaks)

Pérdida de acceso a la memoria asignada sin liberarla. Con el tiempo, agota los recursos del sistema.



// Código vulnerablevoid leak() {    int* data = new int[100];    // Olvidamos delete[] data — fuga}// Versión seguravoid no_leak() {    std::unique_ptr<int[]> data = std::make_unique<int[]>(100);    // La memoria se liberará automáticamente}


Protección: use RAII (punteros inteligentes, contenedores

Blogs

Book Recommendations