flawopen.com/command-injection/C-cpp

● CWE-918 · Crítica
Pesquisa · FlawOpen

Command Injection in C/C++

Learn how to fix Command Injection (CWE-78) in C and C++. Side-by-side vulnerable vs secure code examples for posix_spawn(), execvp(), and system() shell hazards.

💡 Explicação em Linguagem Simples (ELI5)

Imagine pedir a um assistente de escritório para imprimir um documento chamado 'relatorio.pdf'. A injeção de comando ocorre quando alguém fornece o nome 'relatorio.pdf; whoami', e o assistente entrega o bilhete inteiro ao terminal, fazendo-o imprimir o relatório e ler o crachá de administrador.

Conceitos Centrais e Termos

Web Application Security
Componente de arquitetura principal afetado pelo CWE-918.
CWE-918
Classificação padrão Common Weakness Enumeration (CWE) para command-injection-c-cpp.
Defense-in-Depth
Verificação de engenharia em múltiplas camadas e isolamento de limites em tempo de execução.

Fluxo de Ataque Passo a Paso

Step 1

Ingestão de Parâmetros Não Confiáveis

O aplicativo aceita nomes de host diagnósticos, nomes de arquivo ou flags diretamente de uma requisição HTTP ou formulário de usuário.

Step 2

Interpolação de Shell Não Higienizada

O backend constrói uma string de comando shell usando concatenação direta ou formatação em vez de um vetor de argumentos separado.

Step 3

Injeção de Separador de Comandos

O invasor injeta metacaracteres shell como ';', '&&', '|' ou crases (ex: '127.0.0.1; id') para quebrar o contexto pretendido do comando.

Step 4

Execução em Subshell e Comprometimento

O shell do sistema operacional executa o comando anexado com todos os privilégios do processo web em execução.

Código-Fonte: Vulnerável vs. Seguro

✕ IMPLEMENTAÇÃO VULNERÁVEL
// system() invokes /bin/sh with sprintf buffer
#include <stdlib.h>
#include <stdio.h>

void ping_host(const char *user_input) {
    char buffer[256];
    // Attacker input: "127.0.0.1; reboot"
    snprintf(buffer, sizeof(buffer), "ping -c 1 %s", user_input);
    system(buffer);
}
✓ PATCH SEGURO E ROBUSTO
// fork() and execvp() execute binary directly without a shell
#include <unistd.h>
#include <sys/wait.h>

void ping_host(const char *user_input) {
    pid_t pid = fork();
    if (pid == 0) {
        // Child process: arguments are discrete pointers
        char *args[] = {"ping", "-c", "1", (char *)user_input, NULL};
        execvp("ping", args);
        _exit(1);
    } else {
        waitpid(pid, NULL, 0);
    }
}

Lista de Verificação de Segurança para Engenharia

References