Главная / Блог / Command Injection в CTF: находим и эксплуатируем внедрение команд ОС

4 мин.00

Command Injection в CTF: находим и эксплуатируем внедрение команд ОС

Command Injection в CTF: находим и эксплуатируем внедрение команд ОС

Command Injection в CTF: находим и эксплуатируем внедрение команд ОС

На Dojo CTF challenge #36 от YesWeHack участникам подкинули веб-форму с пингом — классическая точка входа для OS command injection. Фильтр на стороне приложения пропускал payload только если в нём не было ни одной латинской буквы: регулярка [a-zA-Z_*^@%+=:,./-] отправляла ввод в санитайзер при первом совпадении. Решением стала ANSI-C нотация $'\143\141\164' — восьмеричные коды символов вместо букв. Из сотен участников таск решили единицы.

Проблема не в сложности уязвимости. Проблема в том, что большинство игроков знают один payload ; cat flag.txt и теряются, когда он не проходит. Дальше — полный разбор эксплуатации command injection в CTF: от первого теста до слепой инъекции и обхода фильтров, которые режут пробелы, буквы и спецсимволы.

Зачем эксплуатация command injection опасна за пределами CTF

Command injection (CWE-78, Improper Neutralization of Special Elements used in an OS Command) возникает, когда пользовательский ввод попадает в системную команду без нейтрализации спецсимволов. По OWASP Top 10:2021, инъекции (A03:2021) — в тройке критичных рисков веб-приложений. В CTF успешная эксплуатация — это флаг. В продакшене — полный контроль сервера: чтение /etc/shadow (T1552.001), загрузка инструментов через curl или wget (T1105) и закрепление в инфраструктуре. Подробнее — в нашем обзоре пентест веб-приложений.

Три CVE в Nagios XI — CVE-2021-25296, CVE-2021-25297, CVE-2021-25298 — все с CVSS 8.8 (HIGH); CVE-2021-25297 и CVE-2021-25298 классифицированы как CWE-78 в NVD, для CVE-2021-25296 CWE не указан. Все три активно эксплуатировались в дикой природе и попали в каталог CISA KEV. EPSS для CVE-2021-25296 — 0.7154 (top 1% по вероятности эксплуатации). По механике каждая из этих CVE идентична тому, что встречается в среднем web CTF: пользовательский ввод попадает в PHP-функцию exec() через вызов ping без валидации. Разница — в масштабе последствий.

Поиск command injection в web CTF уязвимостях

Первый шаг — определить, какой пользовательский ввод доходит до системной команды. Типичные точки входа в CTF-тасках:

  • Формы пинга или проверки доступности — ввод попадает в ping -c 1 <input>
  • DNS-лукапы — ввод уходит в nslookup <input> или dig <input>
  • Конвертеры файлов — вызов ffmpeg, convert, pandoc с пользовательскими аргументами
  • Формы обратной связи — ввод попадает в mail -s "..." -aFrom:<input>

Если таск содержит исходный код, ищите вызовы system(), exec(), shell_exec(), os.system(), subprocess.run() с параметром shell=True, child_process.exec(). Согласно OWASP OS Command Injection Defense Cheat Sheet, именно эти API создают поверхность атаки, потому что вызывают оболочку ОС как посредника. Без исходного кода — тестируйте каждый input-параметр (GET, POST, заголовки, cookie) последовательно, подставляя разделители команд.

Разделители команд и операторы подстановки

Начните с простого — отправьте 127.0.0.1; id и проверьте, появится ли uid=... в ответе. Нет? Перебирайте альтернативные разделители.

Оператор Поведение Linux Windows
; Выполняет команды последовательно Да Нет
& Выполняет обе в фоне Да Да
&& Вторая — только при успехе первой Да Да
\| Stdout первой → stdin второй Да Да
\|\| Вторая — только при ошибке первой Да Да
%0a Перевод строки как разделитель Да Нет
`cmd` Inline-подстановка (backticks) Да Нет
$(cmd) Inline-подстановка (modern) Да Частично

Каждый разделитель ведёт себя по-разному, и в CTF это критично. && выполнит вторую команду только при успехе первой — если ping завершается ошибкой из-за невалидного хоста, payload не сработает. || наоборот — сработает именно из-за ошибки. По данным PortSwigger, размещение & после инъецированной команды (& whoami &) снижает вероятность того, что хвост оригинальной команды помешает выполнению.

Inline-подстановка — `id` и $(id) — заслуживает отдельного внимания. Результат команды подставляется в строку как значение, и это основа для DNS-эксфильтрации при blind injection (об этом ниже).

Предусловия и ограничения: разделитель ; работает только в Unix-шеллах (bash, sh, ash, zsh, dash). В Windows cmd.exe — нет. Backtick-подстановка и $() требуют POSIX-совместимого интерпретатора — не работают в cmd.exe, но работают в PowerShell через $(). Если ввод попадает внутрь одинарных кавычек в оригинальной команде (например, ping -c 1 '<input>'), ни один разделитель не сработает без предварительного закрытия кавычки символом '.

[Применимо: CTF (web), внешний пентест, внутренний пентест — Unix/Windows в зависимости от оператора]

Обход фильтров command injection: пробелы, буквы, спецсимволы

Базовые payload не проходят — значит, есть фильтр. В CTF встречаются три типа: чёрный список символов, чёрный список команд и регулярные выражения. По MITRE CWE-184 (Incomplete List of Disallowed Inputs), denylist-подход систематически проваливается, потому что атакующий находит обходной путь. Именно это делает CTF-таски с фильтрами интересными — по сути, вы ломаете не приложение, а воображение разработчика фильтра.

Обход фильтрации пробелов и спецсимволов

Пробел — первый символ, который режут. Шесть работающих альтернатив:

$IFS — переменная Internal Field Separator, по умолчанию содержит пробел, табуляцию и перевод строки. Payload cat${IFS}/etc/passwd или cat$IFS/etc/passwd выполняет cat /etc/passwd без единого пробела.

{cmd,arg} — brace expansion в bash: {cat,/etc/passwd} раскрывается шеллом в cat /etc/passwd.

< — перенаправление ввода: `cat

Поделиться

0 комментариев

Пожалуйста, войдите, чтобы оставить комментарий.

Загрузка комментариев...