Веб-чат (виджет поддержки) принимает POST-запросы на отправку сообщения и не проверяет, что запрос реально пришёл из нашего фронтенда. В результате злоумышленник может заставить браузер жертвы отправить сообщение в чат от её имени — просто заставив её открыть страницу. Это позволяет подделывать коммуникацию и эскалировать конфликты.
Origin/Referer,
SameSite=Lax или лучше SameSite=Strict, чтобы браузер не пересылал куку в кросс-доменных запросах формой.Origin/Referer: запрос на отправку сообщения должен приходить только с нашего домена.
Мы автоматизируем защиту: пайплайн сам пытается отправить сообщение в чат, ИМЕЯ только куку сессии (как браузер жертвы), но без валидного CSRF-токена и с поддельным Origin. Если сервер всё равно принял сообщение → билд стопаем.
#!/bin/bash
# csrf-chat-check.sh
# имитируем: злоумышленник заставил браузер жертвы отправить POST без CSRF
STATUS=$(curl -s -o /tmp/resp.txt -w "%{http_code}" \
-X POST "https://staging.example.internal/api/v1/widget/messages" \
-H "Content-Type: application/x-www-form-urlencoded" \
-H "Cookie: session=VICTIM_SESSION_COOKIE" \
-H "Origin: https://evil.attacker.site" \
--data "message[content]=test_csrf_message_from_pipeline")
if [ "$STATUS" = "201" ] || [ "$STATUS" = "200" ]; then
echo "[BLOCK] Чат принял сообщение без CSRF и с чужим Origin ($STATUS)"
exit 1
fi
echo "[OK] Чат отклонил запрос без валидного CSRF ($STATUS)"
exit 0
Важно: мы не надеемся на «ребята не забудут включить защиту». Мы делаем так, что билд физически не может уехать в прод, если CSRF снова сломали.
Стандарт: любой state-changing POST в вебе должен проверять, что его инициировал наш фронтенд, а не случайно открытая вкладка.