Path Traversal через абсолютный путь
Обработчик скачивания файлов проверяет только '..' в пути, но не блокирует абсолютные пути (/etc/passwd, /.env). Атакующий может читать любой файл на сервере.
easygolangPro
Задача
# Path Traversal: blacklist-фильтрация ввода
## Сценарий
Вы проводите аудит безопасности интернет-магазина **SecureShop**. Разработчики добавили эндпоинт для скачивания файлов и реализовали «защиту» от обхода каталогов через blacklist подозрительных подстрок в имени файла. Команда уверена, что фильтр покрывает все варианты обхода и эндпоинт безопасен.
## Цель
1. Изучите, что именно фильтрует blacklist, и найдите класс путей, который не блокируется.
2. Прочитайте произвольный файл за пределами разрешённой директории через эндпоинт скачивания.
3. Добудьте файл переменных окружения приложения и получите значение `LAB_FLAG`.
## Теория
Path Traversal через blacklist-фильтрацию — типичный случай, когда защита строится по принципу «запретить опасное», а не «разрешить только безопасное». Любой blacklist по своей природе неполон: он перечисляет известные опасные паттерны, но не покрывает классы payload, которые разработчик не учёл. Stdlib многих языков (включая Go) при чтении файла позволяет передавать как относительные, так и абсолютные пути — это решение принимает вызывающий код, а не файловое API.
**Уязвимый паттерн:**
```go
// Blacklist: проверка одного класса путей не покрывает остальные
if strings.Contains(name, "..") {
http.Error(w, "Invalid path", 400)
return
}
data, _ := os.ReadFile(name) // принимает и абсолютные пути
```
`os.ReadFile`, `ioutil.ReadFile`, `os.Open` и аналоги не отделяют относительные пути от абсолютных. Когда blacklist проверяет только наличие восходящих сегментов, путь, не содержащий запрещённой подстроки, передаётся в ОС напрямую и файл читается с правами процесса приложения.
## Точка входа атаки
`GET /download?name=<имя файла>` — параметр `name` принимает имя файла и возвращает его содержимое.
* **Учётные данные:** `demo` / `demo`
* **Цель:** прочитать файл переменных окружения приложения и извлечь значение `LAB_FLAG`.