Path Traversal через двойное URL-кодирование
Обработчик скачивания файлов применяет filepath.Clean ДО URL-декодирования. Двойное кодирование (%252e%252e%252f) обходит проверку и позволяет читать произвольные файлы.
hardgolangPro
Задача
# Path Traversal: обход нормализации через многоуровневое URL-кодирование
## Сценарий
Вы проводите аудит безопасности интернет-магазина **SecureShop**. Команда добавила эндпоинт для скачивания файлов и реализовала «защиту» от path traversal через стандартную функцию нормализации пути из stdlib. Однако в обработчике одновременно используются и URL-декодирование, и нормализация пути — а порядок их вызовов разработчиками не продуман. Команда уверена, что эндпоинт надёжно защищён.
## Цель
1. Изучите, в каком порядке обработчик применяет URL-декодирование и нормализацию пути.
2. Сформируйте payload, который проходит нормализацию как безобидную строку, но после следующего этапа обработки превращается в обход директории.
3. Прочитайте файл переменных окружения приложения и получите значение `LAB_FLAG`.
## Теория
Многоуровневое URL-кодирование — техника обхода фильтров, основанная на порядке операций декодирования и нормализации в цепочке обработки запроса. HTTP-сервер автоматически выполняет один уровень URL-декодирования перед передачей значения в обработчик; если в коде дополнительно вызывается ручное декодирование (`url.PathUnescape` и аналоги), а защитная нормализация пути (`filepath.Clean`/`Rel` и т.п.) применяется **между** двумя decode-этапами, то итоговая последовательность раскроется только после защитной проверки.
**Уязвимый паттерн:**
```go
// Нормализация применяется к ещё закодированной строке
cleaned := filepath.Clean(name)
decoded, _ := url.PathUnescape(cleaned)
fullPath := filepath.Join(baseDir, decoded) // здесь уже traversal
```
Ключ к атаке — закодировать сам символ `%` (как `%25`) внутри payload. После первого автоматического HTTP-декодирования `%25xx` превращается в `%xx` — это безобидная с точки зрения нормализации строка, в которой нет восходящих сегментов. Защитная проверка её пропускает. Затем второй вызов декодирования (внутри обработчика) раскрывает `%xx` в реальные символы `.` и `/` — и появляется настоящий traversal-обход.
## Точка входа атаки
`GET /download/{name}` — path-параметр `name` принимает имя файла и возвращает его содержимое.
* **Учётные данные:** `demo` / `demo`
* **Цель:** прочитать файл переменных окружения приложения с переменной `LAB_FLAG`.