flawopen.com/command-injection/C-cpp

● CWE-918 · Crítica
Investigación · 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.

💡 Explicación en Lenguaje Sencillo (ELI5)

Imagina pedirle a un asistente de oficina que imprima un documento llamado 'informe.pdf'. La inyección de comandos ocurre cuando alguien entrega el nombre 'informe.pdf; whoami', y el asistente entrega toda la nota al empleado del terminal, imprimiendo el informe y leyendo la credencial del administrador.

Conceptos Clave y Términos

Web Application Security
Componente de arquitectura central afectado por CWE-918.
CWE-918
Clasificación estándar Common Weakness Enumeration (CWE) para command-injection-c-cpp.
Defense-in-Depth
Verificación de ingeniería multicapa y aislamiento de límites en tiempo de ejecución.

Flujo de Ataque Paso a Paso

Step 1

Ingestión de Parámetros No Confiables

La aplicación acepta nombres de host de diagnóstico, nombres de archivo o parámetros directamente desde una solicitud HTTP.

Step 2

Interpolación de Shell Sin Sanitizar

El backend construye la cadena de comando shell concatenando texto directamente en lugar de usar un vector de argumentos seguro.

Step 3

Inyección de Separadores de Comandos

El atacante inyecta metacaracteres de shell como ';', '&&', '|' o comillas invertidas (ej. '127.0.0.1; id') para escapar del comando esperado.

Step 4

Ejecución en Subshell y Control del Host

El shell del sistema operativo ejecuta la instrucción inyectada con todos los permisos del proceso del servidor web.

Código Fuente: Vulnerable vs. Seguro

✕ IMPLEMENTACIÓN VULNERABLE
// 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);
}
✓ PARCHE SEGURO Y 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 Verificación de Seguridad para Ingeniería

References