Deserialization: unserialize() без allowed_classes
Cookie user_prefs десериализуется через unserialize() — подделайте объект с магическим __wakeup() и получите админские права.
mediumphpPro
Задача
# Лаба: Insecure Deserialization — unserialize() без allowed_classes
## Сценарий
SecureShop — интернет-магазин на нативном PHP. После успешного логина приложение сохраняет
пользовательские настройки интерфейса (тема оформления, язык) в cookie `user_prefs`. В этой
cookie хранится сериализованный PHP-объект класса `UserPreferences`, закодированный в base64.
На странице `/profile` сервер декодирует cookie из base64 и восстанавливает объект через
`unserialize()`, чтобы отобразить тему и язык, выбранные пользователем.
Беглый просмотр исходников магазина показывает, что в кодовой базе живёт ещё один класс —
`DevOverride`. Его использовали на этапе разработки для CLI-утилит, и он содержит магический
метод `__wakeup()`, который помечает текущий запрос как админский через глобальный флаг.
В production-сборке этот класс нигде не инстанцируется, но autoload PHP загружает его
вместе со всеми остальными — а значит, он остаётся доступен для `unserialize()`.
## Почему это опасно
`unserialize()` в PHP — не «разобрать строку в массив». Это полноценное восстановление
объектов: PHP создаёт экземпляр указанного в строке класса и сразу вызывает на нём магические
методы (`__wakeup`, `__destruct`, `__toString`, `__call`). Контролируя имя класса в строке,
атакующий выбирает, какой класс из autoload будет создан, и провоцирует исполнение его
магических методов с побочными эффектами. В реальных POP-цепочках Laravel/Symfony/Monolog
такие gadget'ы соединяются в цепочки и достигают RCE.
Вы залогинились как обычный пользователь `demo` (роль `user`). На `/profile` флаг не
отображается — он показывается только пользователям с ролью `admin` или когда выставлен
внутренний dev-флаг. Ваша задача — подменить cookie `user_prefs` так, чтобы `unserialize()`
создал экземпляр класса-гаджета, его магический метод сработал автоматически, и сервер
выдал вам CTF-флаг.
## Цели
1. Проанализировать обработчик профиля в `internal/handlers/handlers.php` — определить, какой cookie
декодируется и какие классы доступны в приложении через autoload.
2. Собрать вручную строку сериализации PHP-объекта с произвольным значением свойства,
опираясь на формат `O:<len>:"ClassName":<n>:{<props>}`.
3. Закодировать полезную нагрузку в base64, URL-encode и подставить в cookie `user_prefs`,
чтобы при заходе на `/profile` сервер вернул CTF-флаг.
## Данные
| Параметр | Значение |
|----------|----------|
| Обычный пользователь | `demo` / `demo` |
| Уязвимый endpoint | `GET /profile` |
| Cookie для атаки | `user_prefs` (base64 + serialize) |
| Класс-gadget в коде | `DevOverride` (смотри `internal/handlers/handlers.php`) |