GateKeeper

Web hard

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}`