Перейти к содержимому
← Каталог php CSRF

CSRF: SameSite=Lax Bypass через GET-запрос

Критичное действие смены пароля выполняется через GET-запрос. SameSite=Lax не защищает от top-level навигации. Сменив пароль администратора через CSRF, залогинься под admin и забери флаг.

mediumphpPro
Задача
# CSRF: SameSite=Lax Bypass через GET-запрос ## Сценарий Интернет-магазин **SecureShop** позволяет авторизованным пользователям менять пароль в настройках профиля через API быстрого доступа. Разработчик ознакомился с современными рекомендациями и выставил атрибут `SameSite=Lax` на сессионную cookie, посчитав, что этого достаточно для защиты от CSRF. Поэтому он не стал добавлять отдельную проверку CSRF-токена для эндпоинта смены пароля и оставил его максимально простым — на стороне сервера запрос принимается обычным GET с параметром `password` в URL. В систему встроен бот-администратор: он принимает ссылку через форму `Report to Admin` и переходит по ней в своей авторизованной сессии. Ваша цель — заставить бота-администратора сменить свой пароль на подконтрольное вам значение, после чего войти под учётной записью `admin` с этим паролем и забрать флаг со страницы профиля. ## Теория **CSRF (Cross-Site Request Forgery)** — атака, при которой злоумышленник заставляет браузер жертвы выполнить запрос на целевой сайт от её имени. Браузер автоматически прикрепляет cookies к любому запросу на нужный домен, поэтому залогиненная сессия жертвы передаётся вместе с запросом, инициированным внешней страницей. Атрибут **`SameSite`** управляет тем, прикрепляются ли cookies к cross-site запросам: * `None` — cookies прикрепляются всегда (требует `Secure`). * `Lax` (значение по умолчанию в современных браузерах) — cookies прикрепляются к **top-level GET-навигации** (переход по ссылке, редирект, `<form method=GET>`, `window.location`). Cross-site POST/PUT/DELETE/AJAX отбрасываются. * `Strict` — cookies прикрепляются **только** если запрос инициирован с того же origin. Главная ошибка в этой лабе — сочетание двух решений, по отдельности нормальных: 1. Мутирующий эндпоинт смены пароля привязан к GET (изменение состояния через идемпотентный метод — антипаттерн). 2. Cookie выставлена с `SameSite=Lax`, который **разрешает** top-level GET-переход. Lax не блокирует top-level GET, поэтому атакующий заставит браузер жертвы перейти по `/api/account/change?password=attacker_value` любым способом — автокликающая `<a href>`, `<meta http-equiv="refresh">`, `window.location = ...`. Cookie уйдёт на сервер вместе с запросом, эндпоинт изменит пароль. **Уязвимый паттерн (двойная ошибка):** В этой лабе сошлись два решения, по отдельности нормальных: 1. **Мутирующая операция смены пароля привязана к GET.** Эндпоинт читает новое значение пароля из параметров URL, хеширует его и пишет в таблицу пользователей. RFC 7231 явно запрещает мутации через GET (§4.2.1), но на уровне кода это просто другой кейс роутера. 2. **Сессионная cookie выставлена с `SameSite=Lax`.** Lax — современное по умолчанию, защищает от cross-site POST/PUT/AJAX, но разрешает top-level GET-навигацию (переход по ссылке, `window.location`, `<meta refresh>`). В обработчике смены пароля **нет** проверки CSRF-токена — разработчик посчитал `SameSite=Lax` достаточным. Поскольку Lax не блокирует top-level GET, любая атакующая страница, открытая в браузере жертвы, может инициировать GET-переход на эндпоинт — и cookie сессии уйдёт вместе с запросом. ## Цели 1. Найдите эндпоинт смены пароля и определите HTTP-метод, который он использует. 2. Подготовьте на exploit-server HTML-страницу, инициирующую top-level GET-навигацию к эндпоинту с подконтрольным значением пароля. 3. Доставьте ссылку через форму `Report to Admin` — бот-администратор посетит её в авторизованной сессии. В результате пароль `admin` сменится на ваш. 4. Войдите в учётную запись `admin` с новым паролем. 5. Заберите флаг со страницы профиля администратора. ## Точка входа атаки | Параметр | Значение | |----------|----------| | Ваш аккаунт | `demo` / `demo` | | Уязвимый эндпоинт | `GET /api/account/change?password=...` | | Cookie защита | `SameSite=Lax` (не блокирует top-level GET) | | Доставка боту | `POST /report` (бот залогинен как admin) | | Проверка текущего пользователя | `GET /api/account/info` — JSON с username и role | | Вход под admin | `POST /login` с новым паролем | | Где появится флаг | `GET /profile` после входа под `admin` (admin владеет товаром «CTF Flag») | | Exploit Server | внешний хостинг для HTML-payload (см. панель лабы) |
🚧 Сайт в разработке. Полный функционал пока недоступен. Все вопросы — support@hackandfix.ru