Cookie Security: HttpOnly, Secure, SameSite, __Host-
Cookie Security: HttpOnly, Secure, SameSite, __Host-
Cookie — главный механизм состояния сессии в HTTP. Флаги HttpOnly, Secure, SameSite и префиксы __Host-/__Secure- определяют, может ли XSS украсть сессию, работает ли CSRF, передаётся ли cookie по HTTP. В статье — полный разбор атрибутов RFC 6265bis с примерами для PHP, Express и nginx.
HttpOnly
Флаг HttpOnly запрещает JavaScript читать cookie через document.cookie. Обязателен для session-cookie — без него любой XSS краннёт токен. Документация — RFC 6265 §4.1.2.6.
Set-Cookie: session=abc123; HttpOnly
Secure
Cookie с Secure передаётся только через SSL/TLS проверку. Без флага браузер отправит её и по HTTP — что делает её уязвимой к MITM. Обязателен для всех cookies на HTTPS-сайте.
Set-Cookie: session=abc123; HttpOnly; Secure
SameSite
SameSite — защита от CSRF. Три значения:
Strict— cookie не идёт вообще в cross-site запросах (даже при клике по внешней ссылке)Lax— идёт при GET-навигации (клик по ссылке) и не идёт при POST/iframe cross-site. Дефолт в современных браузерах.None— идёт всегда; обязывает Secure
Set-Cookie: session=abc123; HttpOnly; Secure; SameSite=Strict
Lax подходит для session-cookie веб-приложений, Strict — для критичных операций (banking), None — для cookie, используемых в сторонних iframe (редко).
__Host- и __Secure- префиксы
Префиксы — это marker-флаги, которые enforce атрибутов:
__Secure-— cookie должна иметь Secure. Даёт protection against attacker-в-соседнем-поддомене от установки твоего имени без Secure.__Host-— Secure + Path=/ + без Domain. Максимальная изоляция: поддомены не могут подсовывать cookie в родительский origin.
Set-Cookie: __Host-session=abc123; HttpOnly; Secure; SameSite=Lax; Path=/
Max-Age vs Expires
Max-Age — в секундах от момента получения, совместим с UTC. Expires — абсолютная дата (устаревает GMT-формат). Используйте Max-Age в современных проектах:
Set-Cookie: session=abc; Max-Age=3600 ← 1 час
Set-Cookie: session=abc; Max-Age=0 ← удалить
PHP
session_set_cookie_params([
'lifetime' => 0,
'path' => '/',
'secure' => true,
'httponly' => true,
'samesite' => 'Strict',
]);
session_start();
setcookie('csrf_token', $token, [
'expires' => time() + 3600,
'path' => '/',
'secure' => true,
'httponly' => true,
'samesite' => 'Strict',
]);
Express / NestJS
app.use(session({
secret: process.env.SESSION_SECRET,
cookie: {
httpOnly: true,
secure: true,
sameSite: 'strict',
maxAge: 3600_000,
},
}));
// или через cookie-parser
res.cookie('token', jwt, {
httpOnly: true,
secure: true,
sameSite: 'strict',
maxAge: 3600_000,
path: '/',
});
Session fixation и regenerate_id
После логина всегда вызывайте session_regenerate_id(true) (PHP) или эквивалент — иначе атакующий может подсунуть свой session-ID до логина.
if (loginSuccess($user, $pass)) {
session_regenerate_id(true);
$_SESSION['user_id'] = $user['id'];
}
Анализ cookies
curl -I https://example.com | grep -i set-cookie
Cookie Security Analyzer enterno.io проверит все cookies сайта, подсветит отсутствующие флаги, trackers и выставит грейд.
FAQ
SameSite=Lax безопасен? Для большинства приложений — да. Для банковских операций рекомендуется Strict + CSRF-токен.
Почему cookie не приходит в cross-domain fetch? Нужно credentials: 'include' + CORS с Allow-Credentials: true + SameSite=None; Secure.
__Host- ломает поддомен? Да — cookie доступна только на точном host. Для app.example.com и API документацию.example.com нужна отдельная cookie.
Можно ли JWT в cookie? Да, и это безопаснее localStorage (HttpOnly защищает от XSS). Добавьте CSRF-токен или SameSite=Strict.
Вывод
Canonical строка session-cookie: HttpOnly; Secure; SameSite=Strict; Path=/; __Host- префикс. Регулярно проверяйте через Cookie Analyzer и Security Scanner. Связанное чтение: Clickjacking, XSS protection.
Проверьте ваш сайт прямо сейчас
Проверить →