Материал

Сессии, куки и режим «запомнить меня»: что проверить перед релизом

Пока команда обсуждает финальный дизайн кнопки, в коде уже живёт тихая уязвимость — неправильно настроенный куки или забытый токен, который не аннулируется при выходе.

Почему сессии — это не «решённая проблема»

Многие команды считают управление сессиями базовой задачей, закрытой фреймворком. Отчасти это правда: современные фреймворки дают удобные дефолты. Но дефолт — не то же самое, что безопасная конфигурация для продакшена. А релизный контекст добавляет давление: перед деплоем нет времени на глубокий ревью, и именно тогда проскакивают конфигурационные ошибки, которые потом живут в продакшене месяцами.

По данным IBM X-Force, средняя стоимость утечки данных в 2024 году составила 4,88 млн долларов [1]. При этом одна из ключевых тенденций 2024–2025 годов — смещение атакующих от взлома учётных данных к краже сессионных токенов: инфостилеры обошли логины и пароли и начали атаковать уже аутентифицированные сессии [2].

Исследователи Constella Intelligence зафиксировали в 2025 году обработку 51,7 миллиона пакетов с украденными данными — рост на 72% по сравнению с предыдущим годом, причём большинство пакетов содержали живые сессионные куки, позволявшие полностью обойти MFA [3]. В 2024 году инфостилеры похитили более 17 миллиардов браузерных кукисов [4].

Цифры означают одно: сессия — это ключ. И то, как команда управляет этим ключом перед каждым релизом, напрямую определяет размер атакуемой поверхности.

Анатомия сессии: что важно понимать перед тем, как проверять

Сессия — это временная связь между пользователем и сервером после аутентификации. Сервер идентифицирует пользователя по session ID, который хранится в браузере. Куки — рекомендованный способ передачи этого идентификатора, потому что правильно настроенный куки недоступен для JavaScript [5].

Есть два принципиально разных вида сессий:

  1. Сессионный куки (session cookie) — без Expires или Max-Age. Живёт до закрытия браузера. Более безопасный, но менее удобный.
  2. Постоянный куки (persistent cookie) — с явным сроком жизни. Переживает закрытие браузера. Именно он используется в режиме «запомнить меня».

MDN Web Docs рекомендует по умолчанию не устанавливать Expires и Max-Age для сессионных кукисов: чем короче жизнь токена, тем меньше окно для атаки [5].

Параллельно существует архитектура на JWT (JSON Web Tokens): stateless-токен, который сервер не хранит. Его валидность подтверждается криптографической подписью, а не запросом к БД. Это даёт масштабируемость, но создаёт проблему с отзывом — JWT остаётся действительным до истечения срока, даже если пользователь уже вышел [6].

Атрибуты куки: минимальный стандарт, который не должен нарушаться

HttpOnly

Запрещает доступ к куки через JavaScript. Это единственная защита от кражи session ID через XSS-атаку. OWASP прямо указывает: HttpOnly — обязателен для всех сессионных кукисов [7].

Исключение — CSRF-токены, которые SPA-фреймворки читают из куки для добавления в заголовок запроса. Только они могут быть без HttpOnly. Все остальные сессионные куки — с ним.

Secure

Куки отправляется только по HTTPS. Без этого атрибута браузер отправит куки и по незашифрованному HTTP — даже если сайт работает на HTTPS. Одного HTTPS на сервере недостаточно: атакующий может вынудить браузер сделать HTTP-запрос и перехватить куки в открытом виде [7].

Важно проверять, что Secure не теряется в staging- и dev-окружениях через переменные среды, которые потом попадают в продакшен.

SameSite

Контролирует, будет ли куки отправлен вместе с кросс-сайтовыми запросами. Три значения:

  • Strict — куки не отправляется ни в каких кросс-сайтовых запросах. Лучшая защита от CSRF, но может ломать переходы с внешних ресурсов (например, ссылка на защищённую страницу из письма не будет работать без повторного логина).
  • Lax — куки отправляется при top-level навигации (переход по ссылке), но не в POST-запросах и iframe. Это браузерный дефолт в Chrome с 2020 года, но явно прописывать лучше, чем полагаться на дефолт.
  • None — куки отправляется всегда. Требует обязательного Secure. Используется только для легитимных кросс-сайтовых сценариев (виджеты, OAuth).

OWASP требует явно указывать SameSite=Strict или SameSite=Lax. Никогда не полагаться на дефолт браузера — он варьируется между версиями и вендорами [7].

Отдельное предупреждение: нельзя устанавливать Domain для куки шире, чем необходимо. Если Domain указан как .example.com, куки будет доступен всем поддоменам. Компрометация одного поддомена — например, через user-controlled content — позволяет атаковать сессии основного домена [8].

Cookie prefixes: __Host- и __Secure-

Механизм, описанный в RFC 6265bis, позволяет браузеру принудительно верифицировать атрибуты куки на уровне имени. Префикс __Host- требует наличия Secure, отсутствия атрибута Domain и значения Path=/. Это предотвращает подмену куки через поддомен и HTTPS-даунгрейд-атаки [7].

OWASP и WSTG рекомендуют именно __Host- для session ID в продакшене [9].

Идеальная конфигурация выглядит так:

Set-Cookie: __Host-SID=<session token>; Path=/; Secure; HttpOnly; SameSite=Strict

Expires / Max-Age: не устанавливать без причины

Если ни Expires, ни Max-Age не указаны — куки исчезает при закрытии браузера. OWASP рекомендует именно это для сессионных кукисов [5]. Явно указывать срок нужно только для режима «запомнить меня» — и тогда выстраивать полноценную инфраструктуру работы с долгоживущими токенами.

Session ID: что проверять в генерации и жизненном цикле

Энтропия

OWASP ASVS (V3) требует минимум 64 бита энтропии для session ID. OWASP Session Management Cheat Sheet рекомендует не менее 128 бит [7][10]. Самостоятельная реализация генератора session ID без использования криптографически стойкого PRNG — типичная ошибка. Используйте стандартные библиотеки фреймворка.

Session ID не должен содержать никакой информации о пользователе: ни ID, ни email, ни временную метку в предсказуемом формате. Он должен быть полностью случайным и иметь смысл только как ключ к серверной сессии.

Перевыпуск после аутентификации

Это защита от session fixation. Атака работает так: злоумышленник получает валидный session ID приложения (часто просто зайдя на сайт), подсовывает этот ID жертве (через ссылку, XSS или другой вектор), жертва проходит аутентификацию с этим ID, — и атакующий, уже зная ID, получает доступ к аутентифицированной сессии [11].

Защита элементарна: генерировать новый session ID сразу после успешной аутентификации и инвалидировать старый. OWASP ASVS 3.2.1 прямо требует этого [10]. Тем не менее это требование регулярно нарушается — особенно в системах, где сессия создаётся ещё до логина для хранения корзины или временных данных.

Проверить можно вручную: зафиксировать session ID до логина (из куки в DevTools), выполнить логин, проверить, изменился ли session ID. Если нет — уязвимость присутствует.

Аналогично: session ID должен меняться при повышении привилегий (sudo-режим, переключение ролей).

Session ID в URL

Никогда. OWASP ASVS 3.1.1 (CWE-598): session ID в URL попадает в логи прокси, историю браузера, Referer-заголовки. Нескольких минут в логе достаточно для компрометации [10].

Тайм-ауты: idle timeout, absolute timeout, renewal timeout

Три независимых механизма, каждый из которых должен присутствовать:

Idle timeout (таймаут бездействия) — сессия аннулируется, если пользователь не проявлял активности в течение N минут. Типичные значения: 15–30 минут для чувствительных приложений (банки, медицина), 1–8 часов для корпоративных инструментов. Важно: браузерный таймаут JavaScript ненадёжен; таймаут должен проверяться на сервере.

Absolute timeout (абсолютный таймаут) — сессия аннулируется независимо от активности через T часов/дней. Даже самый активный пользователь должен периодически проходить повторную аутентификацию. MDN рекомендует эту практику явно [5].

Renewal timeout — при приближении к истечению срока сессии пользователь получает предложение продлить сессию или перелогиниться. Это UX-компромисс, позволяющий не прерывать работу грубо.

Ни один из этих таймаутов не работает, если сессия не аннулируется на сервере. Только удаление/инвалидация server-side записи гарантирует невозможность реплея токена.

Логаут: самое часто упускаемое требование

OWASP WSTG (WSTG-SESS-06) формулирует требование однозначно: логаут должен инвалидировать authentication artifact на стороне сервера. Все сессии, использующие этот артефакт, должны завершаться. Доступ не должен сохраняться до истечения токена [12].

Простой тест: войти, скопировать значение session cookie, выйти, вручную установить скопированный куки в браузере и попробовать открыть защищённую страницу. Если страница открылась — логаут не работает.

Типичные ошибки при логауте:

  • Куки удаляется только на клиенте (установкой Max-Age=0), но сервер продолжает принимать старый токен.
  • JWT-токен остаётся в LocalStorage или куки, но на сервере нет механизма его отзыва.
  • «Запомнить меня» токен не аннулируется при явном логауте.
  • После смены пароля существующие сессии не завершаются.

Специфика JWT при логауте

JWT по природе stateless: сервер не хранит список выданных токенов и не может «удалить» конкретный токен. После логаута JWT остаётся криптографически валидным до истечения exp — это сознательный архитектурный компромисс, а не ошибка [6].

Как компенсировать:

  1. Короткий TTL для access token (5–15 минут). После логаута окно атаки ограничено именно этим временем.
  2. Refresh token rotation: при каждом обновлении access token выдаётся новый refresh token, старый инвалидируется. Использование старого refresh token сигнализирует о возможной компрометации.
  3. Blacklist отозванных токенов (jti-based): при логауте jti токена добавляется в быстрый стор (Redis). Каждый запрос проверяет blacklist. Превращает stateless-систему в stateful, но даёт истинную инвалидацию.
  4. Token introspection: каждый ресурсный сервер запрашивает auth-сервер о статусе токена. Наиболее корректно, но добавляет задержку.

OWASP ASVS 3.3.1 требует, чтобы логаут и истечение срока действия инвалидировали сессионный токен так, чтобы нажатие кнопки «назад» или downstream relying party не возобновляли аутентифицированную сессию [13].

Режим «запомнить меня»: как не превратить удобство в постоянный бэкдор

«Запомнить меня» — это явный запрос пользователя на долгоживущую аутентификацию. Если без флага используется сессионный куки (умирает при закрытии браузера), то с флагом создаётся persistent cookie с токеном, переживающим перезагрузку браузера.

С архитектурной точки зрения правильная реализация выглядит так:

  • Access token — короткоживущий (минуты), хранится в памяти или session cookie.
  • Refresh token — долгоживущий, хранится в HttpOnly; Secure; SameSite=Strict persistent cookie.
  • При наличии «запомнить меня» — Expires на refresh token устанавливается на 30–90 дней (в зависимости от требований безопасности).
  • Без «запомнить меня» — refresh token является session cookie (умирает при закрытии браузера).

Наивная реализация — хранить в куки хэш от username + пароль + время + ключ — принципиально небезопасна. Если атакующий получает куки, он может использовать его до смены пароля. Кроме того, пароль становится частью формулы, и смена пароля аннулирует все "remember me" сессии, но это происходит пассивно, а не активно [14].

Атака с использованием украденного "remember me" токена

Если злоумышленник похитил refresh token (через инфостилер, XSS без HttpOnly, или физический доступ к устройству), он получает возможность аутентифицироваться под пользователем. Без ротации токена этот доступ сохраняется на весь срок жизни куки — даже если пользователь знает о компрометации.

Механизм защиты, описанный в статье Барри Джаспена «Improved Persistent Login Cookie Best Practice» и реализованный в Spring Security PersistentTokenBasedRememberMeServices [15]:

  • Хранить пару (series_id, token) в БД. series_id идентифицирует «chain» сессий, token — конкретную итерацию.
  • При каждом использовании "remember me" куки — token обновляется, series_id остаётся.
  • Если series_id присутствует в БД, но token не совпадает — это признак того, что кто-то уже использовал этот токен. Серию следует инвалидировать и уведомить пользователя.
  • Это не предотвращает первоначальную кражу, но обнаруживает параллельное использование украденного токена.

Что обязательно проверить перед релизом

Для чувствительных операций (смена пароля, платёж, изменение email, удаление аккаунта) "remember me" не должен заменять явную аутентификацию. Даже если пользователь «запомнен», перед критическим действием нужен re-authentication prompt.

После смены пароля все активные "remember me" токены должны аннулироваться — не только текущая сессия. Пользователь должен получить возможность просмотреть список активных сессий и удалить любую из них.

CSRF: SameSite не заменяет полноценную защиту

Распространённое заблуждение: SameSite=Lax решает проблему CSRF. Это не так.

SameSite=Lax защищает от cross-site POST-запросов, но не от top-level GET-навигации. Если приложение выполняет state-changing операции через GET — защита не работает [16]. Кроме того, атакующий может использовать XSS на поддомене (same-site, но не same-origin) для выполнения запросов, которые браузер посчитает «сайтовыми» [17].

OWASP рекомендует комбинировать SameSite с Synchronizer Token Pattern или Double Submit Cookie [8]. Это означает явный CSRF-токен в каждом state-changing запросе, который сервер верифицирует.

Отдельный нюанс: CSRF-куки — единственный тип кукисов, который намеренно делают доступным для JavaScript (без HttpOnly), чтобы SPA мог прочитать его значение и добавить в заголовок. Этот куки не должен содержать сессионный токен — только CSRF-значение.

Практический чеклист: что проверить перед каждым релизом

Блок 1 — Атрибуты кукисов

Проверить каждый Set-Cookie заголовок в ответах приложения:

  1. Все сессионные куки имеют HttpOnly.
  2. Все сессионные куки имеют Secure.
  3. Все сессионные куки имеют явный SameSite=Strict или SameSite=Lax (не полагаться на дефолт браузера).
  4. SameSite=None присутствует только там, где это действительно нужно, и всегда с Secure.
  5. Domain не расширен сверх необходимого (лучше вообще не указывать — тогда куки действует только на текущий домен).
  6. Path минимально необходимый.
  7. Для продакшена рассмотреть использование префиксов __Host- или __Secure-.

Как проверить: curl -I https://yourapp.com/login и анализ Set-Cookie в ответе; DevTools → Application → Cookies.

Блок 2 — Session ID

  1. Session ID генерируется с минимум 64 битами энтропии (лучше 128).
  2. Session ID не содержит предсказуемых компонентов (время, user ID).
  3. Session ID не передаётся в URL (ни в query string, ни во фрагментах).
  4. Новый Session ID генерируется сразу после успешной аутентификации (защита от session fixation).
  5. Session ID меняется при повышении привилегий.

Блок 3 — Тайм-ауты

  1. Idle timeout настроен и проверяется на сервере (не только на клиенте).
  2. Absolute timeout настроен.
  3. Тайм-ауты применяются даже при использовании "remember me".

Блок 4 — Логаут

  1. Логаут аннулирует session token на сервере (не только удаляет куки на клиенте).
  2. После логаута старый session token не принимается (проверить вручную: скопировать куки до логаута, выйти, установить куки вручную, проверить доступ).
  3. После смены пароля все активные сессии кроме текущей аннулируются.
  4. "Remember me" токен аннулируется при явном логауте.
  5. При JWT: access token имеет короткий TTL; refresh token ротируется; есть механизм отзыва.

Блок 5 — Режим «запомнить меня»

  1. "Remember me" реализован через долгоживущий refresh token в HttpOnly; Secure persistent cookie — не через хранение учётных данных.
  2. Токен ротируется при каждом использовании.
  3. Повторное использование старого токена (после ротации) детектируется и обрабатывается как потенциальная компрометация.
  4. Критические операции требуют re-authentication даже при активном "remember me".
  5. Пользователь может просмотреть и отозвать все активные "remember me" сессии.

Блок 6 — CSRF

  1. SameSite установлен, но не является единственной защитой от CSRF.
  2. State-changing операции защищены CSRF-токеном или аналогичным механизмом.
  3. GET-запросы не выполняют state-changing операции.

Блок 7 — Конфигурация окружения

  1. Настройки куки одинаковы между dev/staging/prod (или явно отличаются по документированной причине).
  2. HTTPS включён на всех эндпоинтах, где передаются куки.
  3. HSTS настроен, чтобы первый запрос тоже шёл по HTTPS.

Типичные ошибки и как их обнаружить

Ошибка 1: «Фреймворк настроил всё сам»

Фреймворки дают дефолты — но дефолт не всегда соответствует требованиям продакшена. Django по умолчанию устанавливает SESSION_COOKIE_SAMESITE = 'Lax' и SESSION_COOKIE_HTTPONLY = True, но SESSION_COOKIE_SECURE = False — чтобы работало локально без HTTPS. Если это значение не переопределяется через переменную окружения в продакшене, куки будет отправляться и по HTTP.

Как обнаружить: явно проверять все security-настройки куки через конфигурационный чеклист при каждом деплое.

Ошибка 2: Логаут удаляет куки, но не аннулирует сессию

Классический пример: res.clearCookie('session') на Node.js-сервере. Браузер теряет куки. Но если токен попал к атакующему до логаута — он продолжает работать.

Как обнаружить: ручной тест из блока 4, пункт 17.

Ошибка 3: Слишком широкий Domain

Установка Domain=.example.com делает куки доступным для всех поддоменов: blog.example.com, staging.example.com, user-content.example.com. Если хотя бы один поддомен принимает пользовательский контент — XSS на нём позволяет украсть session cookie основного домена.

Как обнаружить: проверить Domain атрибут всех сессионных кукисов. Если он вообще не нужен — убрать.

Ошибка 4: Session fixation из-за отсутствия перевыпуска Session ID

Частый случай: корзина или временные данные привязываются к session ID ещё до логина (для хранения данных анонимного пользователя). После логина та же сессия «апгрейдится» до аутентифицированной без смены ID. Это и есть классический вектор session fixation.

Правило: при логине всегда создавать новую сессию. Данные из анонимной сессии переносить в новую явно.

Ошибка 5: "Remember me" на основе хэша пароля

Хранить в куки хэш от пароля — значит, что компрометация куки раскрывает информацию, полезную для восстановления пароля. Кроме того, куки остаётся действительным до смены пароля. Правильная реализация — только непредсказуемые случайные токены, без какой-либо связи с учётными данными.

Ошибка 6: JWT без механизма ранней инвалидации

Если access token живёт 24 часа и нет blacklist или introspection endpoint — компрометация одного токена даёт злоумышленнику почти сутки гарантированного доступа. Даже после смены пароля.

Правило: для продакшена TTL access token — не более 15 минут. Refresh token с ротацией. Blacklist для случаев явного отзыва (логаут, смена пароля, подозрительная активность).

Угрозы, которые растут: инфостилеры и cookie replay

С 2020 по 2025 год тактика атакующих принципиально изменилась. Задача больше не «взломать пароль», а «украсть аутентифицированную сессию». Инфостилеры (RedLine, LummaC2, Raccoon, Storm) автоматически извлекают все браузерные куки, сохранённые пароли и сессионные токены с заражённой машины [18].

Ключевое: украденный session cookie позволяет атакующему войти в аккаунт без пароля и без MFA — потому что сессия уже создана, и MFA при входе уже не запрашивается. По данным исследователей Huntress, для инициирования атаки достаточно одного файла лога, и на полный захват окружения уходит около часа [19].

Что это означает для защиты сессий:

  • Короткие TTL сессий сокращают окно, в котором украденный токен полезен атакующему.
  • Привязка сессии к IP-адресу или User-Agent (fingerprinting) — неоднозначная мера: создаёт UX-проблемы при смене сети, но может служить сигналом для детекции аномалий.
  • Детекция аномального поведения сессии (другой IP, другая страна, резкая смена User-Agent) должна запускать re-authentication или уведомление пользователя.
  • Google в Chrome 127 (июль 2024) ввёл App-Bound Encryption — привязку ключей шифрования браузерных данных к самому Chrome. Это существенно усложнило локальную расшифровку для инфостилеров, но не остановило их: новые версии (Storm, 2026) перенесли дешифровку на сторону атакующего сервера [20].

Управление сессиями в контексте микросервисов и SSO

В монолите session ID однозначно идентифицирует сессию на одном сервере. В микросервисной архитектуре и при SSO всё сложнее.

SSO-токен (например, OAuth2 access token или SAML assertion) часто является единственным артефактом, подтверждающим аутентификацию сразу в нескольких приложениях. Компрометация такого токена немедленно распространяется на все связанные системы [12].

OWASP WSTG специально указывает: при SSO нужно тестировать, корректно ли завершается сессия на всех downstream-приложениях при логауте из одного. Backchannel logout (OIDC) или единый механизм отзыва токена должны быть явно реализованы и протестированы перед релизом.

Что делать с этим в CI/CD

Проверки безопасности сессий часто остаются ручными — и поэтому выпадают из процесса под давлением дедлайнов. Разумный подход — встроить базовые проверки в пайплайн:

  • Статический анализ конфигурации: инструменты вроде Semgrep умеют проверять наличие HttpOnly, Secure, SameSite в конфигурации фреймворка прямо в PR. Правила для Django, Express, Spring — доступны в открытых репозиториях.
  • DAST-проверка кукисов: OWASP ZAP в режиме automated scan проверяет атрибуты Set-Cookie заголовков в ответах и выявляет отсутствующие флаги безопасности.
  • Smoke-тест логаута: простой автоматизированный тест — зафиксировать session cookie, выполнить логаут, проверить, что токен больше не принимается — может быть встроен в integration test suite.

Изменения, на которые стоит обращать особое внимание в диффах перед релизом: любые правки в middleware аутентификации, конфигурации кукисов, логике логаута, коде "remember me", настройках TTL токенов, CORS и CSP-политиках. Эти файлы читаются хуже всего под давлением времени — и именно в них чаще всего появляются ошибки, меняющие поведение безопасности всего приложения. Дополнительный слой контроля перед релизом — когда внимание на диф сужено до нескольких критических изменений, а не размыто по всему PR — позволяет не пропустить именно такие правки.

Что говорят стандарты

NIST SP 800-63B-4, финальная версия которого вышла в июле 2025 года, определяет технические требования к аутентификации на трёх уровнях Authenticator Assurance Level (AAL1–AAL3) [21]. Управление сессиями входит в область требований 800-63B, OWASP ASVS V3 (Session Management) формализует их в 14+ проверяемых требованиях для разных уровней зрелости [10].

OWASP WSTG (Web Security Testing Guide) в разделах SESS-01 — SESS-09 описывает конкретные тест-кейсы для каждого аспекта управления сессиями — от проверки атрибутов кукисов до тестирования logout-функциональности и CSRF-защиты [9][12].

Для большинства коммерческих приложений достаточно уровня ASVS L2. Финансовые сервисы, медицинские системы, критическая инфраструктура — L3.

Заключение: управление сессиями — это не «один раз настроить»

Безопасность сессий — не разовая задача на этапе разработки. Это непрерывная проверка, особенно актуальная перед каждым релизом: конфигурация меняется, добавляются новые эндпоинты, обновляются зависимости с дефолтными настройками, команда меняется.

Чеклист из этой статьи — минимальный стандарт. Пройдите по нему перед каждым деплоем в продакшен, автоматизируйте что можно, а остальное сделайте обязательной частью предрелизного ревью.

Конкретный следующий шаг: откройте DevTools прямо сейчас, перейдите на Application → Cookies и проверьте, стоят ли HttpOnly, Secure и SameSite на вашем session cookie. Потом проверьте логаут вручную. Это займёт пять минут — и даст точное понимание, где вы сейчас находитесь.

Источники

[1] IBM — "Cost of a Data Breach Report 2024" — https://www.ibm.com/reports/data-breach

[2] DeepStrike — "Infostealer Malware in 2025: Credential Theft at Scale" — https://deepstrike.io/blog/infostealer-malware-credential-theft-2025

[3] Constella Intelligence — "Google Fixed Session Cookie Theft in Chrome. Here Is What It Cannot Stop." — https://constella.ai/blog/google-just-fixed-session-cookie-theft-in-chrome-here-is-what-it-still-cannot-stop/

[4] DeepStrike — "Stealer Log Statistics 2025: Inside the Credential Theft Boom" — https://deepstrike.io/blog/stealer-log-statistics-2025

[5] MDN Web Docs — "Session management" — https://developer.mozilla.org/en-US/docs/Web/Security/Authentication/Session_management

[6] Descope — "JWT Logout Risks & Mitigations" — https://www.descope.com/blog/post/jwt-logout-risks-mitigations

[7] OWASP — "Session Management Cheat Sheet" — https://cheatsheetseries.owasp.org/cheatsheets/Session_Management_Cheat_Sheet.html

[8] OWASP — "Cross-Site Request Forgery Prevention Cheat Sheet" — https://cheatsheetseries.owasp.org/cheatsheets/Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.html

[9] OWASP WSTG — "Testing for Cookies Attributes" — https://owasp.org/www-project-web-security-testing-guide/latest/4-Web_Application_Security_Testing/06-Session_Management_Testing/02-Testing_for_Cookies_Attributes

[10] OWASP ASVS — "Chapter V3: Session Management" — https://github.com/OWASP/ASVS/blob/master/4.0/en/0x12-V3-Session-management.md

[11] SentinelOne — "Session Fixation: What It Is and How Attackers Hijack User Sessions" — https://www.sentinelone.com/cybersecurity-101/cybersecurity/session-fixation/

[12] OWASP WSTG — "Testing for Logout Functionality" — https://owasp.org/www-project-web-security-testing-guide/latest/4-Web_Application_Security_Testing/06-Session_Management_Testing/06-Testing_for_Logout_Functionality

[13] OWASP ASVS Annotated — "3.3.1 Logout and expiration invalidate the session token" — https://owasp-aasvs4.readthedocs.io/en/latest/3.3.1.html

[14] Medium / Shubham Soni — "Remember Me in Web Applications — How It Works and Why It Matters" — https://medium.com/@sonishubham65/remember-me-in-web-applications-how-it-works-and-why-it-matters-77f0335f2ccd

[15] Baeldung — "Spring Security – Persistent Remember Me" — https://www.baeldung.com/spring-security-persistent-remember-me

[16] PortSwigger Web Security Academy — "Bypassing SameSite cookie restrictions" — https://portswigger.net/web-security/csrf/bypassing-samesite-restrictions

[17] Medium / Airman — "Do SameSite Cookies Solve CSRF?" — https://airman604.medium.com/do-samesite-cookies-solve-csrf-6dcd02dc9383

[18] Coalition — "Infostealers Are Silently Siphoning Businesses' Sensitive Data" — https://www.coalitioninc.com/blog/security-labs/infostealers-are-silently-siphoning-businesses-sensitive-data

[19] Huntress — "From Cookies to Keys: The Threat of Session Hijacking" — https://www.huntress.com/blog/why-hackers-don-t-need-passwords-anymore

[20] BleepingComputer — "The silent 'Storm': New infostealer hijacks sessions, decrypts server-side" — https://www.bleepingcomputer.com/news/security/the-silent-storm-new-infostealer-hijacks-sessions-decrypts-server-side/

[21] NIST — "SP 800-63B-4: Digital Identity Guidelines — Authentication and Authenticator Management" — https://csrc.nist.gov/pubs/sp/800/63/b/4/final

Нужен такой же контроль в ваших изменениях и релизах?

Покажем пример такого замечания на вашем сценарии и соберём пилотный контур без лишней суеты.

Запросить пилот Все статьи
Дальше по теме

Ещё материалы

Все статьи
24 июня 2026 18 мин

Политика использования ИИ в команде разработки: как не опоздать, когда всё уже идёт

Если разработчики уже пишут код с ИИ ассистентами, политика нужна сегодня — а не после первого инцидента TL;DR Более 84% разработчиков уже используют или планируют использовать ИИ инструменты 1 , и большинство делают эт…

Открыть материал
23 июня 2026 16 мин

Регистрация и онбординг пользователей: где появляются первые уязвимости

Форма регистрации выглядит просто. За ней скрывается один из наиболее атакуемых периметров приложения. TL;DR Форма регистрации и онбординг флоу — это первая поверхность атаки, которую видит злоумышленник. Большинство уя…

Открыть материал
23 июня 2026 15 мин

Бизнес-логика и мошенничество в продукте: что проверять до запуска

Ваш продукт работает правильно. Но это не значит, что он работает безопасно. TL;DR Уязвимости бизнес логики — это не сломанный код, а сломанные правила: приложение делает именно то, что написано, но не то, что задумывал…

Открыть материал