flawopen.com/command-injection/Rust

● CWE-918 · Критический
Исследования · FlawOpen

Анализ уязвимости: Command Injection in Rust

Learn how to fix Command Injection (CWE-78) in Rust. Side-by-side vulnerable vs secure code examples for std::process::Command with isolated argument slices.

💡 Простыми словами (ELI5)

Представьте, что вы просите офисного ассистента распечатать документ 'отчет.pdf'. Инъекция команд происходит, когда кто-то указывает имя 'отчет.pdf; whoami', и ассистент слепо передает всю записку терминалу, заставляя его напечатать отчет и прочесть бейдж администратора.

Ключевые понятия и термины

Web Application Security
Технический термин (Web Application Security): Core architecture component affected by CWE-918.
CWE-918
Технический термин (CWE-918): Standard Common Weakness Enumeration classification for command-injection-rust.
Defense-in-Depth
Технический термин (Defense-in-Depth): Multi-layered engineering verification and runtime boundary isolation.

Пошаговый сценарий атаки

Step 1

Прием ненадежных параметров

Приложение принимает диагностические имена хостов, имена файлов или флаги напрямую из HTTP-запроса пользователя.

Step 2

Небезопасная конкатенация командной строки

Бэкенд формирует строку команды оболочки с помощью склеивания строк вместо использования вектора разделенных аргументов.

Step 3

Внедрение разделителей команд

Злоумышленник внедряет метасимволы оболочки, такие как ';', '&&', '|' или обратные кавычки (например, '127.0.0.1; id').

Step 4

Выполнение в подоболочке и компрометация

Командная оболочка ОС выполняет внедренную команду с привилегиями рабочего процесса веб-сервера.

Исходный код: Уязвимый vs Защищённый вариант

✕ УЯЗВИМАЯ РЕАЛИЗАЦИЯ
// Spawning shell explicitly with format! string
use std::process::Command;

fn run_backup(folder: &str) {
    // Attacker input: "data; whoami"
    let cmd = format!("tar -czf backup.tar.gz {}", folder);
    Command::new("sh")
        .arg("-c")
        .arg(&cmd)
        .status()
        .expect("failed");
}
✓ БЕЗОПАСНЫЙ ИСПРАВЛЕННЫЙ ВАРИАНТ
// Calling binary directly with discrete .arg() calls
use std::process::Command;

fn run_backup(folder: &str) {
    // folder is passed as a literal argument to tar, not shell
    Command::new("tar")
        .arg("-czf")
        .arg("backup.tar.gz")
        .arg(folder)
        .status()
        .expect("failed");
}

Чек-лист по защите системы для инженеров

References