Перейти к содержимому
← Каталог golang RCE

Bypass Filters: Строгий WAF

Обход фильтрации пробелов и черного списка команд для RCE.

mediumgolangPro
Задача
# OS Command Injection: Обход naïve WAF на blacklist ## Сценарий Вы продолжаете аудит **SecureShop**. После прошлого инцидента с Network Diagnostics команда разработки добавила «WAF»: список запрещённых подстрок (`;`, `&`, `|`, `printenv`, `cat`, `env`...) и блокировка любых пробелов. Архитектор уверен, что проблема решена. Однако blacklist-подход для command injection — известный антипаттерн: оболочка предоставляет десятки способов выразить одну и ту же команду без запрещённых символов и слов. ## Цель 1. Войдите в админ-панель и откройте инструмент **Network Diagnostics (WAF Protected)**. 2. Определите, какие именно символы и слова блокируются (через эксперименты в форме). 3. Подберите payload, обходящий фильтр одной из техник: `${IFS}`/`$'\t'` вместо пробелов, brace expansion (`{cmd1,cmd2}`), backticks/`$()` без блокированных слов, кодирование через `bash -c "$(echo ZWNobw==|base64 -d)"`. 4. Прочитайте значение переменной окружения `LAB_FLAG` и заберите флаг. ## Теория **WAF на чёрных списках для shell-инъекций** обречён по тем же причинам, что и blacklist для SQLi: пространство «опасных» комбинаций бесконечно, а нормализация на стороне приложения не совпадает с нормализацией оболочки. Распространённые техники обхода: * **`${IFS}` вместо пробела** — `IFS` (Internal Field Separator) по умолчанию содержит пробел/таб/перевод строки; конструкция `cmd1${IFS}cmd2` парсится оболочкой как два аргумента. * **Brace expansion** — `{ping,-c,3,127.0.0.1}` развернётся в `ping -c 3 127.0.0.1` без явных пробелов. * **Подстановка команд через backticks/`$()`** — `` `printenv LAB_FLAG` `` или `$(printenv LAB_FLAG)` исполняет команду и подставляет её вывод. * **Кодирование/обфускация** — `bash<<<<(echo cHJpbnRlbnYgTEFCX0ZMQUc=|base64 -d)` или ANSI-C quoting `$'\x70rintenv\x20LAB_FLAG'`. * **Глобирование** — если запрещено слово `printenv`, помогает `/usr/bin/p?intenv` или `/usr/bin/print*` через wildcards. Корректная защита **не пытается перечислить опасное** — она либо строит allowlist (только цифры/точки/буквы для hostname), либо вообще убирает оболочку из цепочки исполнения, либо заменяет внешнюю команду на эквивалент в стандартной библиотеке Go (например, `net.LookupHost` + `golang.org/x/net/icmp` вместо `ping`). **Уязвимый паттерн (двойная ошибка):** ```go var bannedSubstrings = []string{";", "&", "|", "$(", "`", "printenv", "cat", "env"} func (h *Handler) AdminPing(w http.ResponseWriter, r *http.Request) { host := r.FormValue("host") // (1) Blacklist по подстрокам — десятки способов обхода: for _, banned := range bannedSubstrings { if strings.Contains(host, banned) { http.Error(w, "WAF blocked", 400) return } } if strings.Contains(host, " ") { // (1b) запрет пробелов http.Error(w, "WAF blocked", 400) return } // (2) Команда всё равно идёт через sh -c: cmd := exec.Command("sh", "-c", "ping -c 3 "+host) out, _ := cmd.CombinedOutput() w.Write(out) } ``` ## Точка входа атаки * **Эндпоинт:** `POST /admin/ping` (поле `host`) * **Учётные данные администратора:** `admin` / `LabAdmin2024!` * **Где искать флаг:** значение `LAB_FLAG` в переменных окружения процесса лабы
🚧 Сайт в разработке. Полный функционал пока недоступен. Все вопросы — support@hackandfix.ru