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

Path Traversal (Базовый)

Классическая уязвимость Path Traversal через os.Open.

easygolangPro
Задача
# Path Traversal (Чтение произвольных файлов через скачивание промо-материалов) ## Сценарий Вы проводите аудит безопасности интернет-магазина **SecureShop**. В разделе акций есть страница, позволяющая клиентам скачивать промо-материалы — баннеры, листовки, изображения. Эндпоинт принимает имя файла в GET-параметре, склеивает его с базовой директорией `/lab/static/img/` и открывает через `os.Open`. Никакой проверки, что результирующий путь действительно остался внутри базовой директории, нет — стандартная ошибка-новичок, открывающая чтение любого файла, доступного процессу приложения. ## Цель 1. Найдите эндпоинт скачивания промо-материалов и убедитесь, что он принимает имя файла без валидации. 2. С помощью последовательностей `../` выйдите из базовой директории и подтвердите path traversal на безопасной цели (например, `../../../../etc/passwd`). 3. Прочитайте содержимое файла `/tmp/flag.txt` через эту же уязвимость. 4. Сдайте флаг. ## Теория **Path Traversal** (он же Directory Traversal, dot-dot-slash) — атака, при которой пользователь манипулирует именем файла, чтобы выйти за границы предусмотренной директории. Базовый вектор — добавление последовательностей `../` (или Windows-эквивалентов `..\`) к имени файла: каждая такая последовательность поднимает путь на уровень выше. Если приложение склеивает строки и не нормализует/не проверяет результат, атакующий читает (а иногда и пишет) любые файлы, доступные процессу. Стандартные защитные шаги: 1. **Нормализовать путь** — `filepath.Clean(...)` схлопнет `../` и удалит дублирующиеся `/`. 2. **Проверить, что нормализованный путь начинается с базовой директории** — `strings.HasPrefix(cleaned, baseDir)` или `filepath.Rel(baseDir, cleaned)` без `..` в результате. 3. Только после этого открывать файл. Одной нормализации **недостаточно**: `filepath.Clean` приведёт `/lab/static/img/../../../etc/passwd` в `/etc/passwd`, но `os.Open` его без проблем откроет — нормализация даёт «чистое» имя, а не безопасное. **Уязвимый паттерн:** ```go func (h *Handler) Download(w http.ResponseWriter, r *http.Request) { file := r.URL.Query().Get("file") // Конкатенация без проверки + os.Open. ../ в имени выводит за пределы базы: fullPath := "/lab/static/img/" + file f, err := os.Open(fullPath) if err != nil { http.Error(w, "Not Found", 404); return } defer f.Close() io.Copy(w, f) } ``` ## Точка входа атаки * **Эндпоинт:** `GET /download?file=<имя_файла>` * **Базовая директория:** `/lab/static/img/` * **Где лежит флаг:** `/tmp/flag.txt`
🚧 Сайт в разработке. Полный функционал пока недоступен. Все вопросы — support@hackandfix.ru