Стройте ответ вокруг владения состоянием, лимитов, отказа и восстановления. Определение становится инженерным ответом только в конкретном production-сценарии.
Вопросы и ответы
36 подробных ответов
Проверка по первоисточникам опубликована для 1 из 36 ответов. Дата и область проверки указаны у каждого проверенного ответа.
01В чём разница между аутентификацией и авторизацией?
junior
Короткий ответ: Аутентификация — «кто ты?» (проверка личности). Авторизация — «что тебе можно?» (проверка прав). Сначала аутентификация, потом авторизация.
Подробно:
- Authentication (AuthN) — установление личности. Пользователь доказывает, что он тот, за кого себя выдаёт: логин+пароль, токен, отпечаток, сертификат. Результат — система знает, кто это.
- Authorization (AuthZ) — проверка, что аутентифицированный субъект имеет право выполнить действие или получить доступ к ресурсу. Результат — «можно» или «нельзя» (часто
403 Forbidden).
Пример HTTP-статусов:
401 Unauthorized— на самом деле «не аутентифицирован» (неверный/отсутствующий токен).403 Forbidden— аутентифицирован, но не авторизован (прав не хватает).
Запрос → [AuthN: кто ты?] → [AuthZ: тебе можно это?] → ресурс
↓ нет ↓ нет
401 403
⚠️ Ловушка: Названия HTTP-статусов вводят в заблуждение: 401 Unauthorized относится к аутентификации, а не к авторизации. Авторизация — это 403 Forbidden.
02Как работает session-based аутентификация?
junior
Короткий ответ: После логина сервер создаёт сессию, хранит её состояние у себя и отдаёт клиенту session id в cookie. На каждом запросе браузер шлёт cookie, сервер по id находит сессию.
Подробно:
- Пользователь шлёт логин/пароль.
- Сервер проверяет, создаёт запись сессии (например,
{userId: 42, role: admin}) в хранилище и генерирует случайный непредсказуемыйsession id. - Сервер ставит cookie:
Set-Cookie: sid=abc123; HttpOnly; Secure; SameSite=Lax. - Браузер автоматически прикладывает cookie ко всем последующим запросам на тот же домен.
- Сервер по
sidдостаёт сессию и понимает, кто это.
Сессия — stateful: состояние живёт на сервере, у клиента только указатель (id).
Set-Cookie: sid=8f3a...; HttpOnly; Secure; SameSite=Strict; Max-Age=3600; Path=/
⚠️ Ловушка: session id должен быть криптографически случайным и достаточно длинным. Если его можно предсказать или перебрать — это session hijacking. Никогда не кладите в id предсказуемые данные (например, инкрементный userId).
03Где и как хранятся сессии на сервере?
middle
Короткий ответ: В серверном хранилище: в памяти, в Redis/Memcached или в БД. В распределённых системах — централизованно (Redis), иначе сессия «привязана» к одному инстансу.
Подробно:
- In-memory (память процесса) — быстро, но теряется при рестарте и не работает с несколькими инстансами без sticky sessions.
- Redis / Memcached — стандарт для продакшена: быстро, поддерживает TTL (автоистечение), общий для всех инстансов.
- БД — надёжно, но медленнее.
При горизонтальном масштабировании сессии должны быть в общем хранилище, иначе пользователь, попавший на другой инстанс через балансировщик, окажется «разлогинен». Альтернатива — sticky sessions (балансировщик всегда шлёт пользователя на тот же сервер), но это хрупко.
⚠️ Ловушка: Хранение сессий в памяти инстанса — главная причина «случайных разлогинов» после деплоя/масштабирования. Это частый аргумент в пользу JWT (stateless), но у JWT свои минусы (см. ниже).
04Что такое JWT и как он устроен?
middle
Короткий ответ: JWT (JSON Web Token) — самодостаточный токен из трёх частей header.payload.signature, закодированных в Base64URL и разделённых точками. Подпись гарантирует целостность.
Подробно:
eyJhbGciOiJIUzI1NiJ9 . eyJzdWIiOiI0MiIsInJvbGUiOiJhZG1pbiJ9 . SflKxwRJ...
header (Base64URL) payload (Base64URL) signature
- Header — алгоритм и тип:
{"alg":"HS256","typ":"JWT"}. - Payload — claims (утверждения). Стандартные:
sub(subject/userId),iss(issuer),aud(audience),exp(expiry),iat(issued at),nbf(not before). Плюс кастомные:role,email. - Signature — подпись от
base64(header) + "." + base64(payload)секретным ключом.
JWT stateless: вся информация внутри токена, серверу не нужно хранить состояние — он только проверяет подпись.
Плюсы: stateless, легко масштабировать, удобно для микросервисов и межсервисной аутентификации, не нужен round-trip к хранилищу сессий. Минусы: нельзя легко отозвать, размер больше cookie с session id, данные внутри видны всем (только подписаны, не зашифрованы).
⚠️ Ловушка: Payload не зашифрован, а только закодирован Base64URL и подписан. Любой может прочитать содержимое. Никогда не кладите в JWT пароли, токены карт, PII — это публично читаемо. Base64 ≠ шифрование.
05HS256 vs RS256 — в чём разница?
middle
Короткий ответ: HS256 — симметричный (один общий секрет для подписи и проверки, HMAC-SHA256). RS256 — асимметричный (приватный ключ подписывает, публичный проверяет, RSA-SHA256).
Подробно:
- HS256 (HMAC) — секрет один. Кто проверяет, тот же может и подписать (подделать). Подходит, когда тот же сервис и выдаёт, и проверяет токены.
- RS256 (RSA) — приватным ключом подписывает только auth-сервер, а публичным ключом любой сервис может проверить, не имея возможности подделать. Идеально для микросервисов и сторонних потребителей.
HS256: sign(secret) → verify(secret) // один ключ
RS256: sign(privKey) → verify(pubKey) // пара ключей
⚠️ Ловушка: Классическая атака «alg: none» и «alg confusion»: злоумышленник меняет header на alg:none (без подписи) или на HS256, используя публичный RSA-ключ как HMAC-секрет. Защита: на сервере жёстко фиксируйте ожидаемый алгоритм, не доверяйте полю alg из токена.
06Как сервер валидирует JWT?
middle
Короткий ответ: Сервер проверяет криптографическую защиту JWT доверенной библиотекой и допустимым алгоритмом, затем валидирует обязательные claims. Для HMAC нужен общий секрет; для RSA/ECDSA проверяют подпись публичным ключом издателя, а не вычисляют её заново приватным ключом.
Подробно: Для подписанного JWT (JWS):
- Выбрать допустимый алгоритм из настройки сервера, а не слепо доверять
algиз токена. Получить соответствующий доверенный ключ;kidне должен позволять загрузить произвольный URL или файл. - Проверить MAC (HMAC) или цифровую подпись (например, RS256/ES256) над исходным
header.payload. - Проверить требуемые
exp,nbf,iss,audс ограниченным допуском часов.iatописывает время выпуска; политика сервиса определяет допустимый возраст токена. - Использовать claims для авторизации только после успешной проверки всех условий.
Криптографическая проверка возможна без БД, но отзыв токенов, блокировка пользователя или актуальные права могут требовать дополнительного состояния. Декодирование Base64 не является валидацией. Не реализуйте криптографию и сравнение MAC вручную.
Источники: JWT, JWT Best Current Practices.
07Почему JWT сложно отозвать и что с этим делать?
senior
Короткий ответ: JWT stateless — сервер не хранит выданные токены, поэтому до истечения exp токен валиден всегда, даже если пользователь разлогинился или забанен. Решения: короткий TTL + refresh, blacklist, версии токенов.
Подробно: При сессиях достаточно удалить запись из хранилища — и доступ закрыт мгновенно. С JWT такой кнопки нет. Подходы:
- Короткий TTL (5–15 мин) у access-токена + refresh-токен. Тогда «окно» компрометации мало.
- Blacklist / denylist — хранить отозванные jti в Redis с TTL до их
exp. Это возвращает stateful-составляющую (компромисс). - Token versioning — хранить
tokenVersionу пользователя; при logout/смене пароля инкрементировать. В токене кладётся версия, при проверке сверяется с БД (тоже round-trip).
⚠️ Ловушка: «JWT = можно сделать logout удалением на клиенте» — миф. Удаление токена в браузере не делает его невалидным на сервере; если копия утекла, она работает до exp. Реальный logout требует серверной денилист-логики или коротких TTL.
09Зачем нужны refresh tokens и что такое token rotation?
senior
Короткий ответ: Access-токен короткоживущий (минуты) для запросов; refresh-токен долгоживущий и используется только для получения новых access-токенов. Rotation — каждый refresh выдаёт новый refresh-токен и инвалидирует старый.
Подробно:
- Access token — короткий TTL, шлётся в каждый запрос; если утечёт, быстро протухнет.
- Refresh token — длинный TTL, хранится максимально защищённо (HttpOnly cookie / secure storage), шлётся только на endpoint обновления.
- Token rotation — при каждом использовании refresh-токена сервер выдаёт новую пару и помечает старый refresh использованным. Если кто-то попытается переиспользовать старый refresh — reuse detection: значит, токен украден, сервер отзывает всю цепочку (logout всех сессий).
[access 10м] истёк → POST /refresh (refresh-токен) → новый access + новый refresh
старый refresh → инвалидирован
⚠️ Ловушка: Без rotation и reuse-detection украденный refresh-токен даёт злоумышленнику бесконечный доступ. Refresh-токены нужно хранить на сервере (stateful) для возможности отзыва — это «возврат» к состоянию, но только для refresh, не для каждого запроса.
10Sessions vs JWT — когда что выбрать?
middle
Короткий ответ: Сессии — для классических веб-приложений с одним бэкендом, когда нужен мгновенный отзыв. JWT — для stateless API, микросервисов, межсервисной аутентификации и масштабирования без общего хранилища.
Подробно:
| Критерий | Session (stateful) | JWT (stateless) |
|---|---|---|
| Хранение состояния | На сервере (Redis/БД) | В токене у клиента |
| Отзыв | Мгновенный (удалить запись) | Сложный (blacklist/TTL) |
| Масштабирование | Нужно общее хранилище | Легко, ничего не хранить |
| Round-trip к хранилищу | На каждый запрос | Не нужен (только проверка подписи) |
| Размер | Маленький (id в cookie) | Больше (весь payload) |
| Микросервисы | Неудобно | Удобно |
| Утечка | Сессию убили — конец | Действует до exp |
💡 На практике часто гибрид: JWT access-токен (короткий) + серверный refresh с возможностью отзыва.
⚠️ Ловушка: JWT выбирают «потому что stateless и модно», а потом добавляют blacklist для отзыва — и теряют главное преимущество (statelessness). Если нужен мгновенный отзыв и приложение монолитное — сессии проще и безопаснее.
11OAuth 2.0 — роли и зачем он нужен?
middle
Короткий ответ: OAuth 2.0 — протокол делегированной авторизации: позволяет приложению получить ограниченный доступ к ресурсам пользователя на другом сервисе, не зная его пароль. Это про доступ, не про логин.
Подробно — четыре роли:
- Resource Owner — пользователь, владелец данных.
- Client — приложение, которое хочет доступ (например, сторонний сервис).
- Authorization Server — выдаёт токены (например, accounts.google.com).
- Resource Server — API, где лежат данные и который проверяет access-токен (например, Google Drive API).
Пример: приложение хочет читать ваши фото в Google. Вместо ввода пароля Google в чужом приложении вы логинитесь у Google и даёте согласие на scope photos.read. Приложение получает access-токен с этим scope.
⚠️ Ловушка: OAuth 2.0 — это авторизация (доступ к ресурсам), а не аутентификация (кто вошёл). Использовать «голый» OAuth2 для логина («Login with X») неправильно — для этого есть OpenID Connect (см. ниже). Частая ошибка: считать access-токен доказательством личности.
12OAuth 2.0 — какие бывают grant types?
senior
Короткий ответ: Основной сегодня — Authorization Code + PKCE. Для сервер-к-серверу — Client Credentials. Implicit и Resource Owner Password Credentials устарели и не рекомендуются.
Подробно:
- Authorization Code + PKCE — стандарт для веба, SPA и мобильных. Клиент получает короткий
codeчерез редирект, затем меняет его на токен на бэкенде. PKCE (code_verifier/code_challenge) защищает от перехвата кода у публичных клиентов. - Client Credentials — машина-машина, без пользователя. Сервис аутентифицируется своими credentials и получает токен.
- Implicit (устарел) — токен сразу в редиректе/URL; уязвим (токен в истории браузера, логах). Заменён на Auth Code + PKCE.
- Resource Owner Password Credentials (ROPC) (устарел) — приложение собирает логин/пароль пользователя напрямую; противоречит сути OAuth, использовать нельзя.
Auth Code + PKCE:
client → /authorize?code_challenge=... → login+consent → redirect ?code=XYZ
client → /token (code=XYZ, code_verifier=...) → access_token (+refresh, +id_token)
⚠️ Ловушка: Если на собеседовании предлагают Implicit или Password grant для нового приложения — это red flag. Сегодня для всех клиентов (включая SPA) рекомендуется Authorization Code + PKCE.
13Access token vs refresh token в OAuth?
middle
Короткий ответ: Access-токен — для обращения к Resource Server, короткоживущий. Refresh-токен — для получения новых access-токенов без повторного логина, долгоживущий, идёт только на Authorization Server.
Подробно: Access-токен предъявляется в Authorization: Bearer <token> ресурс-серверу. Когда истекает, клиент использует refresh-токен на token-endpoint auth-сервера и получает новый access-токен. Refresh никогда не шлётся ресурс-серверу.
⚠️ Ловушка: Не путать scope (что разрешено токену) с identity. Access-токен может быть «непрозрачным» (opaque) — тогда ресурс-сервер валидирует его через introspection-endpoint, а не разбирает сам.
14OpenID Connect (OIDC) vs OAuth2?
senior
Короткий ответ: OIDC — слой аутентификации поверх OAuth 2.0. OAuth2 отвечает «что можно» (авторизация доступа), OIDC добавляет «кто вошёл» (аутентификация) через id_token.
Подробно:
- OAuth2 даёт access_token для доступа к API.
- OIDC дополнительно выдаёт id_token — это JWT с информацией о пользователе (claims:
sub,email,name,iss,aud,exp). Именно он подтверждает личность. - OIDC добавляет стандартизированный
/userinfoendpoint и discovery (.well-known/openid-configuration).
«Login with Google/Apple/GitHub» = OIDC, а не чистый OAuth2.
⚠️ Ловушка: access_token нельзя использовать для аутентификации пользователя — он непрозрачен для клиента и предназначен ресурс-серверу. Для «кто это» нужен id_token. Путаница access/id-token — частая ошибка реализации SSO.
15Что такое SSO и SAML?
middle
Короткий ответ: SSO (Single Sign-On) — один вход для доступа к множеству приложений. SAML — XML-протокол обмена аутентификационными данными (assertions) между Identity Provider и Service Provider, популярен в enterprise.
Подробно:
- SSO — пользователь логинится один раз у Identity Provider (IdP), затем заходит в разные приложения (SP) без повторного ввода пароля. Реализуется через SAML, OIDC, Kerberos.
- SAML 2.0 — старый, но живой в корпоративном мире (Okta, AD FS). IdP отправляет подписанный XML-assertion с личностью пользователя в SP. Тяжеловесный (XML, подписи), но широко поддержан.
- OIDC — современная альтернатива SAML на JSON/JWT, легче для мобильных и SPA.
⚠️ Ловушка: SAML-assertions подписываются XML-подписью; уязвимости XML Signature Wrapping позволяли подделывать assertion. Нужно строго валидировать подпись всего документа и доверять только корректно подписанным элементам.
16Как правильно хранить пароли?
junior
Короткий ответ: Никогда в открытом виде и не обычным хешем. Используйте специализированные медленные алгоритмы: argon2 (предпочтительно), bcrypt или scrypt — с солью, встроенной в алгоритм.
Подробно:
- Пароли хранят как хеш, не обратимый.
- Обычные хеши (MD5, SHA-1, SHA-256) слишком быстрые — GPU считает миллиарды в секунду, перебор и rainbow tables эффективны.
- Алгоритмы для паролей специально медленные и настраиваемые по cost-фактору:
- argon2id — победитель Password Hashing Competition, устойчив к GPU и memory-hard атакам. Рекомендуется сегодня.
- bcrypt — проверенный, с work factor (cost). Ограничение длины пароля ~72 байта.
- scrypt — memory-hard, тоже хорош.
hash = bcrypt(password, cost=12) // соль генерируется и хранится внутри строки хеша
⚠️ Ловушка: «Я добавил соль к SHA-256, этого хватит» — нет. Соль убивает rainbow tables, но не спасает от brute force быстрым хешем. Нужен именно медленный алгоритм. И не пишите свою криптографию — используйте библиотеки.
17Salt, pepper и почему медленный хеш — это хорошо?
middle
Короткий ответ: Salt — уникальная случайная строка на каждый пароль, хранится рядом с хешем, защищает от rainbow tables и одинаковых хешей у одинаковых паролей. Pepper — общий секрет, хранимый отдельно от БД. Медленный хеш делает перебор экономически невыгодным.
Подробно:
- Salt — добавляется к паролю до хеширования. Уникален на пользователя ⇒ два одинаковых пароля дают разные хеши, и предрасчитанные таблицы бесполезны. Соль не секрет, обычно лежит в той же строке (bcrypt/argon2 включают её автоматически).
- Pepper — дополнительный секрет, не хранящийся в БД (в env/vault/HSM). Если БД утечёт без pepper, перебор невозможен без секрета. Дополнительный слой.
- Медленный хеш — даже если БД украдена, перебор каждого пароля занимает заметное время; при cost-факторе можно подстраивать «дороговизну» под рост железа.
⚠️ Ловушка: Соль не должна быть глобально одинаковой для всех («статическая соль») — это, по сути, pepper, а не соль, и не защищает от того, что одинаковые пароли дают одинаковые хеши. Соль — на каждого пользователя своя.
18Hashing vs Encryption vs Encoding?
middle
Короткий ответ: Encoding — обратимое преобразование без секрета (Base64), не безопасность. Encryption — обратимое с ключом (шифрование). Hashing — необратимое (одностороннее). Их постоянно путают.
Подробно:
| Обратимо? | Нужен ключ/секрет? | Назначение | |
|---|---|---|---|
| Encoding (Base64, URL-encode) | Да, кто угодно | Нет | Представление данных, не защита |
| Encryption (AES, RSA) | Да, с ключом | Да | Конфиденциальность |
| Hashing (SHA-256, bcrypt) | Нет | Нет (бывает salt/pepper) | Целостность, проверка паролей |
Пароли — хешируют (необратимо). Данные, которые нужно прочитать обратно (номер карты для платежа) — шифруют. Base64 — это просто кодировка, она никого не «защищает».
⚠️ Ловушка: «Я закодировал пароль в Base64» — это не защита, любой декодирует мгновенно. JWT-payload тоже только Base64URL — читается всеми. Encoding ≠ encryption ≠ hashing.
19Симметричное vs асимметричное шифрование?
middle
Короткий ответ: Симметричное — один ключ для шифрования и расшифровки (AES), быстрое. Асимметричное — пара ключей: публичный шифрует/проверяет, приватный расшифровывает/подписывает (RSA, ECC), медленнее, решает проблему обмена ключами.
Подробно:
- Симметричное (AES) — быстро, для больших объёмов данных. Проблема: как безопасно передать общий ключ обеим сторонам.
- Асимметричное (RSA, ECC) — публичный ключ можно раздавать всем; зашифрованное им расшифровывается только приватным. Используется для обмена ключами и цифровых подписей.
- На практике гибрид: TLS использует асимметрику для согласования общего сеансового ключа, затем симметрику (AES) для самих данных — лучшее из двух миров.
⚠️ Ловушка: Асимметричное шифрование не используют для больших данных напрямую — оно медленное и ограничено размером ключа. Им шифруют только сам симметричный ключ.
20Зачем нужен HTTPS/TLS?
junior
Короткий ответ: TLS обеспечивает конфиденциальность (шифрование трафика), целостность (нельзя незаметно изменить) и аутентичность сервера (сертификат). Защищает от перехвата и MITM-атак.
Подробно: Без HTTPS трафик идёт открытым текстом — провайдер,公 Wi-Fi, любой на пути может читать пароли, cookie, данные и подменять контент. TLS:
- Шифрует — нельзя прочитать перехваченное.
- Целостность — нельзя подменить пакеты незаметно.
- Аутентичность — сертификат, подписанный CA, подтверждает, что вы общаетесь с настоящим сервером, а не с прокладкой.
MITM (Man-in-the-Middle) — атакующий встаёт между клиентом и сервером, читает/меняет трафик. TLS+валидный сертификат не даёт это сделать незаметно (клиент увидит ошибку сертификата).
⚠️ Ловушка: HTTPS защищает данные в пути, но не от XSS, SQLi, утечки БД или плохой авторизации. «У нас HTTPS, значит безопасно» — заблуждение. Также флаг cookie Secure обязателен, иначе cookie уйдёт и по HTTP.
21Что такое OWASP Top 10?
middle
Короткий ответ: Список 10 наиболее критичных рисков веб-безопасности от OWASP, обновляемый периодически. Это базовый чек-лист, что проверять.
Подробно (OWASP Top 10, версия 2021, ключевые):
- Broken Access Control — самый частый: IDOR, обход проверок прав, повышение привилегий.
- Cryptographic Failures — слабое/отсутствующее шифрование, пароли в открытом виде, данные по HTTP.
- Injection — SQLi, command injection, LDAP injection (XSS тоже относят сюда).
- Insecure Design — изъяны на уровне архитектуры, отсутствие threat modeling.
- Security Misconfiguration — дефолтные пароли, открытые админки, лишние заголовки/фичи, неверный CORS.
- Vulnerable and Outdated Components — устаревшие зависимости с известными CVE.
- Identification and Authentication Failures — слабые пароли, отсутствие MFA, плохие сессии.
- Software and Data Integrity Failures — небезопасные обновления, десериализация, CI/CD-цепочка.
- Security Logging and Monitoring Failures — нет логов/алертов на атаки.
- Server-Side Request Forgery (SSRF) — сервер заставляют ходить на внутренние ресурсы.
⚠️ Ловушка: Broken Access Control — №1, но именно его чаще всего недооценивают, полагаясь на «фронт не покажет кнопку». Авторизацию проверяет сервер на каждом запросе.
22SQL injection — как работает и как защититься?
middle
Короткий ответ: Атака, где ввод пользователя попадает в SQL-запрос как код, а не как данные. Защита — параметризованные запросы (prepared statements), ORM, валидация ввода.
Подробно: Уязвимый код конкатенирует ввод:
# УЯЗВИМО
query = "SELECT * FROM users WHERE name = '" + name + "'"
# ввод: name = "' OR '1'='1" → вернёт всех пользователей
# ввод: name = "'; DROP TABLE users;--" → удалит таблицу
Защита — параметризованные запросы: значения передаются отдельно от текста запроса, СУБД трактует их строго как данные:
# БЕЗОПАСНО
cursor.execute("SELECT * FROM users WHERE name = %s", (name,))
- ORM (SQLAlchemy, Hibernate, Prisma) по умолчанию параметризует.
- Принцип наименьших привилегий для БД-пользователя приложения.
- Валидация/allowlist для динамических частей (имена колонок нельзя параметризовать — только allowlist).
⚠️ Ловушка: ORM не панацея — raw()-запросы, динамические ORDER BY/имена таблиц и LIKE с конкатенацией всё ещё уязвимы. Параметризовать можно только значения, не идентификаторы — для них нужен строгий allowlist.
23XSS — виды и защита?
middle
Короткий ответ: Cross-Site Scripting — внедрение чужого JS в страницу, исполняемого в браузере жертвы. Виды: stored, reflected, DOM-based. Защита — экранирование вывода, CSP, HttpOnly cookie.
Подробно:
- Stored XSS — вредоносный скрипт сохраняется на сервере (комментарий, профиль) и отдаётся всем посетителям. Самый опасный.
- Reflected XSS — скрипт в параметре запроса отражается в ответе (например, страница поиска), срабатывает по ссылке-приманке.
- DOM-based XSS — уязвимость в клиентском JS, который небезопасно вставляет данные в DOM (
innerHTML,document.write), сервер не участвует.
Что может XSS: украсть cookie/токены, делать запросы от имени жертвы, кейлоггер, дефейс.
Защита:
- Экранирование вывода по контексту (HTML, атрибут, JS, URL). Современные фреймворки (React, Angular) экранируют по умолчанию.
- CSP (Content-Security-Policy) — ограничивает источники скриптов, блокирует inline-скрипты.
HttpOnlycookie — JS не прочитает токен (снижает кражу).- Избегать
innerHTML/dangerouslySetInnerHTML/evalс пользовательскими данными; санитизировать HTML (DOMPurify).
⚠️ Ловушка: Экранировать нужно по контексту вывода, а не «на входе». Одна и та же строка безопасна в тексте HTML, но опасна внутри <script> или атрибута href="javascript:...". Слепая фильтрация на входе ломает данные и не закрывает все контексты.
24CSRF — как работает атака и защита?
middle
Короткий ответ: Cross-Site Request Forgery — заставляет браузер жертвы выполнить нежелательный запрос на сайт, где она авторизована, используя автоматически прикладываемые cookie. Защита: CSRF-токен, SameSite cookie, проверка Origin/Referer.
Подробно: Жертва залогинена в банке (cookie сессии). Заходит на сайт атакующего, где есть скрытая форма/картинка:
<img src="https://bank.com/transfer?to=attacker&amount=1000">
Браузер автоматически приложит cookie банка к этому запросу — перевод уйдёт от имени жертвы. Атакующий не видит ответ, но действие выполнено.
Защита:
- CSRF-токен (synchronizer token) — сервер выдаёт непредсказуемый токен в форме/заголовке; чужой сайт его не знает.
SameSite=Lax/Strictна cookie — браузер не шлёт cookie при кросс-сайтовых запросах. Современная основная защита.- Проверка
Origin/Refererзаголовков на сервере. - Использовать безопасные методы: state-changing операции только через POST/PUT/DELETE, не GET.
⚠️ Ловушка: CSRF актуален только когда аутентификация автоматическая (cookie). Если токен в Authorization-заголовке (его браузер сам не приложит), классический CSRF не работает — но появляется XSS-риск хранения. SameSite=Lax не защищает полностью при некоторых GET-навигациях.
25CORS и same-origin policy?
senior
Короткий ответ: Same-Origin Policy запрещает JS читать ответы с другого origin. CORS — механизм, которым сервер разрешает кросс-доменные запросы через заголовки Access-Control-*. CORS ослабляет SOP, а не защищает сервер.
Подробно:
- Origin = схема + хост + порт.
https://a.comиhttps://b.com(или другой порт/схема) — разные origin. - Same-Origin Policy (SOP) — браузерное правило: скрипт с одного origin не может читать ответ от другого origin.
- CORS — сервер с помощью заголовков говорит браузеру, кому можно:
Access-Control-Allow-Origin: https://app.comAccess-Control-Allow-Methods: GET, POSTAccess-Control-Allow-Headers: Authorization, Content-TypeAccess-Control-Allow-Credentials: true(разрешить cookie)
- Preflight — для «непростых» запросов (методы кроме GET/POST/HEAD, кастомные заголовки) браузер сначала шлёт
OPTIONS, чтобы спросить разрешение, и только потом основной запрос.
Browser → OPTIONS /api (preflight) → Access-Control-Allow-Origin: https://app.com
Browser → POST /api (если разрешено)
⚠️ Ловушка: CORS — это НЕ защита сервера. Он управляет тем, что браузер разрешает читать JS-у. Запрос всё равно доходит до сервера (curl/Postman игнорируют CORS). Опасная мисконфигурация: Access-Control-Allow-Origin: * вместе с Allow-Credentials: true (спецификация это запрещает) или рефлексия Origin без проверки allowlist — открывает доступ любому сайту к данным пользователя. CORS не заменяет аутентификацию/авторизацию.
26Авторизация: RBAC vs ABAC, scopes, least privilege?
middle
Короткий ответ: RBAC — права через роли (admin, editor). ABAC — права через атрибуты (отдел, время, владелец). Scopes — гранулярные разрешения токена. Least privilege — давать минимально необходимое.
Подробно:
- RBAC (Role-Based) — пользователю назначают роли, ролям — права. Просто, но грубо при сложных правилах.
- ABAC (Attribute-Based) — решение по атрибутам субъекта, ресурса и контекста: «менеджер может видеть документ, если он автор ИЛИ из того же отдела И рабочее время». Гибко, сложнее в поддержке.
- Scopes — в OAuth/токенах: что разрешено токену (
read:orders,write:profile). - Principle of Least Privilege — каждый компонент/пользователь получает только тот доступ, что строго нужен. Меньше прав — меньше ущерб при компрометации.
⚠️ Ловушка: Авторизацию надо проверять на сервере на каждом запросе и на уровне объекта (этот пользователь имеет право на ЭТУ запись?), а не только «у роли есть доступ к эндпоинту». Иначе — IDOR. Скрытие кнопки на фронте — не авторизация.
27Rate limiting и защита от brute force?
middle
Короткий ответ: Ограничение числа запросов за интервал (по IP/пользователю/ключу). Защищает от перебора паролей, DoS, скрейпинга. Дополняется account lockout, CAPTCHA, экспоненциальной задержкой.
Подробно:
- Rate limiting — алгоритмы token bucket, sliding window. Ответ
429 Too Many Requestsпри превышении. - Brute force защита для логина:
- Прогрессивная задержка (экспоненциальный backoff) после неудач.
- Account lockout — временная блокировка после N неудач.
- CAPTCHA после нескольких ошибок.
- Мониторинг credential stuffing (попытки известных утёкших паролей).
- Лимиты лучше вешать и на уровне IP, и на уровне аккаунта (чтобы distributed-атака с многих IP не обошла per-IP лимит).
⚠️ Ловушка: Жёсткий account lockout сам становится вектором DoS: атакующий нарочно блокирует чужие аккаунты, перебирая пароли. Часто лучше прогрессивная задержка + MFA + мониторинг, чем глухая блокировка. И не раскрывайте, существует ли логин («неверный логин или пароль» — единое сообщение).
28Secrets management — как хранить секреты?
middle
Короткий ответ: Никогда не хранить секреты (ключи, пароли БД, токены) в коде/репозитории. Использовать переменные окружения, а лучше — секрет-менеджеры (Vault, AWS Secrets Manager, KMS) с ротацией и аудитом.
Подробно:
- Не в коде/Git — секрет в репозитории = утёк навсегда (история, форки). Если попал — ротировать немедленно, не просто удалить коммит.
- Env vars / .env — базовый уровень;
.envв.gitignore. Лучше чем хардкод, но не идеал (видны в окружении процесса, дампах). - Secret managers / Vault — централизованное хранение, шифрование at-rest, контроль доступа, аудит, ротация, динамические короткоживущие credentials.
- KMS/HSM — для ключей шифрования.
- Сканеры секретов в CI (git-secrets, trufflehog, gitleaks) — ловить утечки до коммита.
⚠️ Ловушка: Удалить секрет из последнего коммита недостаточно — он остаётся в истории Git и у всех, кто склонировал. Единственно правильно — ротировать (отозвать) скомпрометированный секрет.
29Заголовки безопасности (CSP, HSTS, X-Frame-Options)?
middle
Короткий ответ: HTTP-заголовки, которыми сервер инструктирует браузер усилить защиту: CSP (источники ресурсов), HSTS (только HTTPS), X-Frame-Options (анти-clickjacking), X-Content-Type-Options (анти-MIME-sniffing).
Подробно:
Content-Security-Policy— белый список источников скриптов/стилей/картинок; главная защита от XSS и инъекций. Пример:default-src 'self'; script-src 'self'.Strict-Transport-Security(HSTS) — браузер всегда использует HTTPS для домена, даже если ввели http.max-age=31536000; includeSubDomains. Защита от SSL-stripping.X-Frame-Options: DENY/SAMEORIGIN— запрещает встраивать страницу в<iframe>⇒ защита от clickjacking. (Современный эквивалент —frame-ancestorsв CSP.)X-Content-Type-Options: nosniff— браузер не «угадывает» MIME-тип, использует заявленный ⇒ защита от исполнения замаскированных файлов.- Дополнительно:
Referrer-Policy,Permissions-Policy, отсутствиеServer/X-Powered-By(информационная гигиена).
⚠️ Ловушка: CSP легко сделать бесполезным: script-src 'unsafe-inline' 'unsafe-eval' или * сводят защиту на нет. Внедрять CSP надо постепенно (report-only режим), иначе сломаете легитимные скрипты.
30IDOR — Insecure Direct Object Reference?
middle
Короткий ответ: Уязвимость, когда приложение даёт доступ к объекту по его идентификатору без проверки, что у пользователя есть право на ЭТОТ объект. Подвид Broken Access Control.
Подробно: Эндпоинт GET /api/invoices/1043 возвращает счёт по id. Если сервер не проверяет, что счёт принадлежит текущему пользователю, атакующий просто меняет id на 1044, 1045 и читает чужие данные.
GET /api/orders/1001 (мой) → 200 OK
GET /api/orders/1002 (чужой) → должно быть 403, но возвращает 200 = IDOR
Защита:
- Проверять владение/права на уровне объекта на каждом запросе (
WHERE id=? AND owner_id=currentUser). - Не полагаться на «непредсказуемость» id; UUID помогает от угадывания, но не заменяет проверку прав.
⚠️ Ловушка: «У нас id — длинный UUID, угадать нельзя» — это security through obscurity. UUID не заменяет проверку авторизации: ссылка может утечь, и доступ всё равно должен проверяться.
31Mass assignment?
senior
Короткий ответ: Уязвимость, когда приложение слепо маппит все поля из тела запроса в объект модели, позволяя пользователю задать поля, которые он не должен (isAdmin, role, balance).
Подробно: Форма обновления профиля шлёт {name, email}. Но клиент добавляет {"name":"X","email":"y","isAdmin":true}, и если код делает user.update(request.body) без фильтрации — пользователь становится админом.
// УЯЗВИМО
user.update(req.body); // принимает любые поля
// БЕЗОПАСНО — allowlist полей (DTO)
const { name, email } = req.body;
user.update({ name, email });
Защита: allowlist разрешённых полей (strong parameters в Rails, DTO/binding-модели, @JsonIgnore), отдельные input-модели от доменных.
⚠️ Ловушка: Использовать одну и ту же ORM-модель и для приёма входных данных, и как доменную сущность — прямой путь к mass assignment. Разделяйте входные DTO и сущности.
322FA, MFA, TOTP?
middle
Короткий ответ: MFA — несколько факторов аутентификации (что-то знаешь / имеешь / есть ты). 2FA — частный случай (два фактора). TOTP — одноразовый код по времени из приложения-аутентификатора.
Подробно:
- Факторы: знание (пароль), владение (телефон, ключ), биометрия (отпечаток).
- 2FA = пароль + второй фактор. Резко снижает риск компрометации при утечке пароля.
- TOTP (Time-based One-Time Password) — приложение (Google Authenticator, Authy) и сервер делят общий секрет; код вычисляется из секрета + текущего времени (окно ~30 сек). Не требует сети.
- Методы 2FA по надёжности: аппаратные ключи (WebAuthn/FIDO2/U2F) > TOTP-приложение > SMS (уязвим к SIM-swap, перехвату).
⚠️ Ловушка: SMS как второй фактор — слабый (SIM-swap, перехват SS7). Предпочтительнее TOTP или аппаратные ключи. Также важна защита процесса восстановления/recovery codes — иначе MFA обходят через «забыли доступ».
33Почему нельзя хранить пароли в открытом виде и зачем медленный хеш?
concept
Короткий ответ: При утечке БД открытые пароли мгновенно компрометируют всех (и другие сайты — люди переиспользуют пароли). Хеш необратим. Медленный хеш делает массовый перебор экономически нецелесообразным.
Подробно: Даже сотрудники не должны видеть пароли. Хранят необратимый хеш — при логине хешируют введённое и сравнивают. Но быстрый хеш (SHA-256) перебирается миллиардами в секунду на GPU. Медленный (argon2/bcrypt) с настраиваемым cost замедляет каждую попытку в тысячи раз ⇒ перебор украденной базы становится непрактичным. Соль убирает rainbow tables и одинаковость хешей.
⚠️ Ловушка: «Зашифрую пароли AES» — плохо: шифрование обратимо, и при утечке ключа все пароли вскрываются. Пароли именно хешируют, а не шифруют.
35Чем XSS опаснее CSRF?
concept
Короткий ответ: XSS исполняет произвольный код атакующего в браузере жертвы — он может всё, что может пользователь, читать токены, обходить CSRF-токены, кейлоггить. CSRF лишь заставляет выполнить конкретное предугаданное действие вслепую.
Подробно: При CSRF атакующий не видит ответ и ограничен заранее известными запросами; защищается SameSite/CSRF-токеном. При XSS код выполняется в контексте сайта: читает DOM, ответы, локальные токены, считывает и подставляет CSRF-токен из страницы, делает любые аутентифицированные запросы. То есть XSS обходит CSRF-защиту. Поэтому XSS — фундаментально опаснее.
⚠️ Ловушка: Защита от CSRF (CSRF-токены) не помогает против XSS — скрипт на странице сам прочитает этот токен. Сначала закрывают XSS.
36Что значит «не доверяй клиенту»?
concept
Короткий ответ: Любые данные и проверки на клиенте (браузер, мобильное приложение) могут быть подделаны. Все проверки безопасности — валидация, авторизация, лимиты — должны дублироваться и быть авторитетными на сервере.
Подробно: Клиент полностью под контролем пользователя: можно изменить JS, отправить запрос через curl/Postman, подменить заголовки, цены, id, скрытые поля, обойти валидацию формы. Поэтому:
- Валидация на фронте — только UX, серверная — обязательна.
- Авторизация — на сервере на каждом запросе и каждом объекте (не «скрыли кнопку»).
- Цены, скидки, права, количество — пересчитывать/проверять на сервере, не верить значениям из запроса (см. mass assignment).
⚠️ Ловушка: Скрытое поле, disabled-кнопка, проверка только на фронте, «секретный» эндпоинт без авторизации — всё это обходится тривиально. Сервер — единственная граница доверия.
Источники
Источники и редакционная политика
Ссылки на источники помогают изучить тему глубже. Если для ответа опубликована техническая проверка, рядом указаны её дата и область. Мы не связаны с упомянутыми работодателями и не продаём места в подборках. Источники, функции сервисов и формат найма могут меняться.
От чтения к воспроизведению
Отрепетируйте полный цикл интервью.
RecallDeck возвращает сложные темы по расписанию и помогает удерживать в памяти язык, SQL, архитектуру и поведенческие истории.