Segurança de aplicações C++: top 10 vulnerabilidades e como evitá-las

Treinador Online de Python para Iniciantes

Aprenda Python facilmente sem sobrecarga teórica. Resolva tarefas práticas com verificação automática e escreva código diretamente no navegador.

Start Course
Aqui está a tradução do conteúdo educacional HTML do russo para o português (Português do Brasil), mantendo todas as tags HTML e os termos técnicos em inglês:

Segurança de aplicações C++: top 10 vulnerabilidades e métodos de proteção



C++ é uma linguagem de programação poderosa e flexível, usada para criar sistemas de alto desempenho, desde jogos até software financeiro e sistemas operacionais. No entanto, esse poder tem um custo: o desenvolvedor gerencia a memória manualmente, o que abre caminho para inúmeras vulnerabilidades. De acordo com OWASP e CWE, erros em código C++ constituem uma parte significativa das brechas críticas em software.



Neste artigo, vamos analisar as 10 principais vulnerabilidades mais perigosas do C++, mostrar exemplos de código vulnerável e dar dicas práticas para preveni-las. O material será útil tanto para desenvolvedores iniciantes quanto para experientes que buscam escrever código robusto e seguro.



1. Estouro de buffer (Buffer Overflow)



Esta é uma vulnerabilidade clássica e uma das mais perigosas. Ocorre quando o programa escreve dados além dos limites do buffer alocado. Um invasor pode sobrescrever áreas de memória adjacentes (endereço de retorno, dados) e obter controle sobre a execução.



Exemplo vulnerável:

#include <iostream>#include <cstring>

void vulnerable_function(const char* input) { char buffer[10]; strcpy(buffer, input); // Sem verificação de tamanho! std::cout << buffer << std::endl;}

int main() { vulnerable_function("AAAAAAAAAAAAAAAAAAAA"); // Estouro return 0;}


Como se proteger:

  • Use alternativas seguras: strncpy, snprintf, std::string.
  • Verifique o comprimento dos dados de entrada antes de copiar.
  • Ative flags do compilador: -fstack-protector-strong (GCC/Clang) e /GS (MSVC).
  • Use sanitizers: -fsanitize=address para detectar erros de memória.


2. Vazamentos de memória (Memory Leaks)



O vazamento de memória ocorre quando a memória alocada dinamicamente não é liberada. Com o tempo, isso leva ao esgotamento da memória, negação de serviço (DoS) e operação instável do aplicativo.



Exemplo vulnerável:

void leak_memory() {    int* data = new int[1000]; // Aloca memória    // ... trabalha com data ...    // Esquece delete[] data;}


Como se proteger:

  • Use smart pointers: std::unique_ptr, std::shared_ptr, std::vector.
  • Aplique RAII (Resource Acquisition Is Initialization).
  • Use regularmente ferramentas de análise: Valgrind, AddressSanitizer, Dr. Memory.


// Versão segura com smart pointer#include <memory>void safe_function() {    auto data = std::make_unique<int[]>(1000);    // A memória será liberada automaticamente ao sair do escopo}


3. Data Race e Race Condition



Ocorrem quando múltiplas threads acessam dados compartilhados simultaneamente sem sincronização. Levam a comportamento imprevisível, corrupção de dados e bugs difíceis de detectar.



Exemplo vulnerável:

#include <thread>#include <iostream>

int counter = 0; // Variável compartilhada

void increment() { for (int i = 0; i < 100000; ++i) { counter++; // Operação não atômica }}

int main() { std::thread t1(increment); std::thread t2(increment); t1.join(); t2.join(); std::cout << "Counter: " << counter << std::endl; // Resultado imprevisível return 0;}


Como se proteger: