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

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

Мутирующий эндпоинт смены email реализован через GET. SameSite=Lax не защищает от top-level навигации. Измени email администратора через CSRF.

mediumgolangPro
Задача
# CSRF: SameSite=Lax Bypass через GET-эндпоинт ## Сценарий Вы проводите аудит безопасности интернет-магазина **SecureShop**. Разработчик добавил быстрый эндпоинт смены email через GET-запрос: `GET /api/email/change?email=...` — «удобный для CLI и тестирования». Команда уверена, что приложение защищено от CSRF, потому что cookie сессии выставлена с атрибутом `SameSite=Lax`. Это распространённое заблуждение: `Lax` блокирует только cross-site POST/PUT/DELETE, но **разрешает cookies при top-level GET-навигации** — переход по ссылке, редирект, `window.location.href = ...`. ## Цель 1. Разберитесь, почему `SameSite=Lax` не защищает GET-эндпоинты, выполняющие мутации (изменение состояния). 2. Подготовьте на exploit-server HTML-страницу с автоматическим переходом на уязвимый GET-URL (через `<meta refresh>`, `window.location` или просто `<a href>` + автоклик). 3. Через форму `/report` отправьте ссылку боту-администратору. Бот откроет страницу — браузер выполнит top-level GET-навигацию на `GET /api/email/change?email=...` со своими admin-cookie. 4. Email администратора изменится — после этого **флаг появится в каталоге** `/catalog`, в карточке товара «CTF Flag» (сервер подставляет его, обнаружив смену email администратора). ## Теория **`SameSite` cookie attribute** управляет тем, прикрепляются ли cookies к cross-site запросам. Возможные значения: * `None` — cookies прикрепляются всегда (требует `Secure`). * `Lax` (значение по умолчанию во многих современных браузерах) — cookies прикрепляются к **top-level GET-навигации** (переход по ссылке, редирект, `<form method=GET>`). Cross-site POST/PUT/DELETE/AJAX отбрасываются. * `Strict` — cookies прикрепляются **только** если запрос инициирован с того же origin. Полностью блокирует CSRF, но ломает UX: переход на сайт по внешней ссылке выглядит как «вы не залогинены». Главная ошибка в этой лабе — сочетание двух решений, по отдельности нормальных: 1. Уязвимый эндпоинт принимает GET-запрос с побочным эффектом (изменение email). 2. Cookie выставлена с `SameSite=Lax`. Lax не блокирует top-level GET, поэтому атакующий может заставить браузер жертвы перейти по `https://target/api/email/change?email=attacker@evil.com` любым способом — `<a href>` + автоклик, `<meta http-equiv="refresh">`, `window.location = ...`. Cookie уйдёт на сервер вместе с запросом, эндпоинт изменит email. **Уязвимый паттерн (двойная ошибка):** ```go // (1) Маршрут смены email привязан к GET — мутация через идемпотентный метод: mux.HandleFunc("GET /api/email/change", h.ChangeEmail) // (2) Cookie выставлена с SameSite=Lax — Lax разрешает top-level GET: http.SetCookie(w, &http.Cookie{ Name: "session_token", Value: token, Path: "/", SameSite: http.SameSiteLaxMode, // Lax не защищает GET-мутацию HttpOnly: true, }) func (h *Handler) ChangeEmail(w http.ResponseWriter, r *http.Request) { user := h.getUser(r) if user == nil { /* 401 */ return } newEmail := r.URL.Query().Get("email") // GET-параметр h.db.Exec("UPDATE users SET email=? WHERE id=?", newEmail, user.ID) } ``` ## Точка входа атаки | Параметр | Значение | |----------|----------| | Ваш аккаунт | `demo` / `demo` | | Уязвимый эндпоинт | `GET /api/email/change?email=...` | | Доставка боту | `POST /report` | | Где появится флаг | `GET /catalog` — карточка «CTF Flag» (после успешной CSRF) | | Exploit Server / hosting | внешний хостинг для HTML-payload (см. панель лабы) |
🚧 Сайт в разработке. Полный функционал пока недоступен. Все вопросы — support@hackandfix.ru