Перейти к содержанию
Бэкенд и системы

36 вопросов по теме «аутентификация и безопасность backend» на собеседовании

В этом материале — 36 вопросов из русской колоды RecallDeck по теме «аутентификация и безопасность backend». Сначала сформулируйте короткий ответ сами, затем откройте подробный разбор и проверьте примеры, ограничения и отказные случаи.

23 мин чтения36 подробных ответовПроверено 24 августа 2026
Главная мысль

Стройте ответ вокруг владения состоянием, лимитов, отказа и восстановления. Определение становится инженерным ответом только в конкретном production-сценарии.

Вопросы и ответы

36 подробных ответов

01

В чём разница между аутентификацией и авторизацией?

Короткий ответ: Аутентификация — «кто ты?» (проверка личности). Авторизация — «что тебе можно?» (проверка прав). Сначала аутентификация, потом авторизация.

Подробно:

  • Authentication (AuthN) — установление личности. Пользователь доказывает, что он тот, за кого себя выдаёт: логин+пароль, токен, отпечаток, сертификат. Результат — система знает, кто это.
  • Authorization (AuthZ) — проверка, что аутентифицированный субъект имеет право выполнить действие или получить доступ к ресурсу. Результат — «можно» или «нельзя» (часто 403 Forbidden).

Пример HTTP-статусов:

  • 401 Unauthorized — на самом деле «не аутентифицирован» (неверный/отсутствующий токен).
  • 403 Forbidden — аутентифицирован, но не авторизован (прав не хватает).
Запрос → [AuthN: кто ты?] → [AuthZ: тебе можно это?] → ресурс
            ↓ нет                  ↓ нет
           401                    403

⚠️ Ловушка: Названия HTTP-статусов вводят в заблуждение: 401 Unauthorized относится к аутентификации, а не к авторизации. Авторизация — это 403 Forbidden.

02

Как работает session-based аутентификация?

Короткий ответ: После логина сервер создаёт сессию, хранит её состояние у себя и отдаёт клиенту session id в cookie. На каждом запросе браузер шлёт cookie, сервер по id находит сессию.

Подробно:

  1. Пользователь шлёт логин/пароль.
  2. Сервер проверяет, создаёт запись сессии (например, {userId: 42, role: admin}) в хранилище и генерирует случайный непредсказуемый session id.
  3. Сервер ставит cookie: Set-Cookie: sid=abc123; HttpOnly; Secure; SameSite=Lax.
  4. Браузер автоматически прикладывает cookie ко всем последующим запросам на тот же домен.
  5. Сервер по sid достаёт сессию и понимает, кто это.

Сессия — stateful: состояние живёт на сервере, у клиента только указатель (id).

Set-Cookie: sid=8f3a...; HttpOnly; Secure; SameSite=Strict; Max-Age=3600; Path=/

⚠️ Ловушка: session id должен быть криптографически случайным и достаточно длинным. Если его можно предсказать или перебрать — это session hijacking. Никогда не кладите в id предсказуемые данные (например, инкрементный userId).

03

Где и как хранятся сессии на сервере?

Короткий ответ: В серверном хранилище: в памяти, в Redis/Memcached или в БД. В распределённых системах — централизованно (Redis), иначе сессия «привязана» к одному инстансу.

Подробно:

  • In-memory (память процесса) — быстро, но теряется при рестарте и не работает с несколькими инстансами без sticky sessions.
  • Redis / Memcached — стандарт для продакшена: быстро, поддерживает TTL (автоистечение), общий для всех инстансов.
  • БД — надёжно, но медленнее.

При горизонтальном масштабировании сессии должны быть в общем хранилище, иначе пользователь, попавший на другой инстанс через балансировщик, окажется «разлогинен». Альтернатива — sticky sessions (балансировщик всегда шлёт пользователя на тот же сервер), но это хрупко.

⚠️ Ловушка: Хранение сессий в памяти инстанса — главная причина «случайных разлогинов» после деплоя/масштабирования. Это частый аргумент в пользу JWT (stateless), но у JWT свои минусы (см. ниже).

04

Что такое JWT и как он устроен?

Короткий ответ: 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 ≠ шифрование.

05

HS256 vs RS256 — в чём разница?

Короткий ответ: 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?

Короткий ответ: Пересчитывает подпись по header+payload своим ключом и сравнивает с подписью токена; проверяет exp, iss, aud, nbf. Если что-то не сходится — токен невалиден.

Подробно:

  1. Разбить токен на три части.
  2. Пересчитать подпись от header.payload ключом и сравнить с третьей частью.
  3. Проверить exp (не истёк), nbf/iat (время), iss (тот, кому доверяем), aud (предназначен нам).
  4. Только после успешной проверки доверять claims (role, sub).

Валидация чисто криптографическая и не требует обращения к БД — в этом сила stateless.

⚠️ Ловушка: Никогда не доверяйте payload без проверки подписи. И не парсите токен «руками» без проверки exp/alg — используйте проверенную библиотеку. Сравнение подписи должно быть constant-time, чтобы исключить timing-атаки.

07

Почему JWT сложно отозвать и что с этим делать?

Короткий ответ: 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?

Короткий ответ: 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, не для каждого запроса.

10

Sessions vs JWT — когда что выбрать?

Короткий ответ: Сессии — для классических веб-приложений с одним бэкендом, когда нужен мгновенный отзыв. JWT — для stateless API, микросервисов, межсервисной аутентификации и масштабирования без общего хранилища.

Подробно:

Критерий Session (stateful) JWT (stateless)
Хранение состояния На сервере (Redis/БД) В токене у клиента
Отзыв Мгновенный (удалить запись) Сложный (blacklist/TTL)
Масштабирование Нужно общее хранилище Легко, ничего не хранить
Round-trip к хранилищу На каждый запрос Не нужен (только проверка подписи)
Размер Маленький (id в cookie) Больше (весь payload)
Микросервисы Неудобно Удобно
Утечка Сессию убили — конец Действует до exp

💡 На практике часто гибрид: JWT access-токен (короткий) + серверный refresh с возможностью отзыва.

⚠️ Ловушка: JWT выбирают «потому что stateless и модно», а потом добавляют blacklist для отзыва — и теряют главное преимущество (statelessness). Если нужен мгновенный отзыв и приложение монолитное — сессии проще и безопаснее.

11

OAuth 2.0 — роли и зачем он нужен?

Короткий ответ: 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-токен доказательством личности.

12

OAuth 2.0 — какие бывают grant types?

Короткий ответ: Основной сегодня — 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.

13

Access token vs refresh token в OAuth?

Короткий ответ: Access-токен — для обращения к Resource Server, короткоживущий. Refresh-токен — для получения новых access-токенов без повторного логина, долгоживущий, идёт только на Authorization Server.

Подробно: Access-токен предъявляется в Authorization: Bearer <token> ресурс-серверу. Когда истекает, клиент использует refresh-токен на token-endpoint auth-сервера и получает новый access-токен. Refresh никогда не шлётся ресурс-серверу.

⚠️ Ловушка: Не путать scope (что разрешено токену) с identity. Access-токен может быть «непрозрачным» (opaque) — тогда ресурс-сервер валидирует его через introspection-endpoint, а не разбирает сам.

14

OpenID Connect (OIDC) vs OAuth2?

Короткий ответ: OIDC — слой аутентификации поверх OAuth 2.0. OAuth2 отвечает «что можно» (авторизация доступа), OIDC добавляет «кто вошёл» (аутентификация) через id_token.

Подробно:

  • OAuth2 даёт access_token для доступа к API.
  • OIDC дополнительно выдаёт id_token — это JWT с информацией о пользователе (claims: sub, email, name, iss, aud, exp). Именно он подтверждает личность.
  • OIDC добавляет стандартизированный /userinfo endpoint и discovery (.well-known/openid-configuration).

«Login with Google/Apple/GitHub» = OIDC, а не чистый OAuth2.

⚠️ Ловушка: access_token нельзя использовать для аутентификации пользователя — он непрозрачен для клиента и предназначен ресурс-серверу. Для «кто это» нужен id_token. Путаница access/id-token — частая ошибка реализации SSO.

15

Что такое SSO и SAML?

Короткий ответ: 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

Как правильно хранить пароли?

Короткий ответ: Никогда в открытом виде и не обычным хешем. Используйте специализированные медленные алгоритмы: 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 быстрым хешем. Нужен именно медленный алгоритм. И не пишите свою криптографию — используйте библиотеки.

17

Salt, pepper и почему медленный хеш — это хорошо?

Короткий ответ: Salt — уникальная случайная строка на каждый пароль, хранится рядом с хешем, защищает от rainbow tables и одинаковых хешей у одинаковых паролей. Pepper — общий секрет, хранимый отдельно от БД. Медленный хеш делает перебор экономически невыгодным.

Подробно:

  • Salt — добавляется к паролю до хеширования. Уникален на пользователя ⇒ два одинаковых пароля дают разные хеши, и предрасчитанные таблицы бесполезны. Соль не секрет, обычно лежит в той же строке (bcrypt/argon2 включают её автоматически).
  • Pepper — дополнительный секрет, не хранящийся в БД (в env/vault/HSM). Если БД утечёт без pepper, перебор невозможен без секрета. Дополнительный слой.
  • Медленный хеш — даже если БД украдена, перебор каждого пароля занимает заметное время; при cost-факторе можно подстраивать «дороговизну» под рост железа.

⚠️ Ловушка: Соль не должна быть глобально одинаковой для всех («статическая соль») — это, по сути, pepper, а не соль, и не защищает от того, что одинаковые пароли дают одинаковые хеши. Соль — на каждого пользователя своя.

18

Hashing vs Encryption vs Encoding?

Короткий ответ: 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 асимметричное шифрование?

Короткий ответ: Симметричное — один ключ для шифрования и расшифровки (AES), быстрое. Асимметричное — пара ключей: публичный шифрует/проверяет, приватный расшифровывает/подписывает (RSA, ECC), медленнее, решает проблему обмена ключами.

Подробно:

  • Симметричное (AES) — быстро, для больших объёмов данных. Проблема: как безопасно передать общий ключ обеим сторонам.
  • Асимметричное (RSA, ECC) — публичный ключ можно раздавать всем; зашифрованное им расшифровывается только приватным. Используется для обмена ключами и цифровых подписей.
  • На практике гибрид: TLS использует асимметрику для согласования общего сеансового ключа, затем симметрику (AES) для самих данных — лучшее из двух миров.

⚠️ Ловушка: Асимметричное шифрование не используют для больших данных напрямую — оно медленное и ограничено размером ключа. Им шифруют только сам симметричный ключ.

20

Зачем нужен HTTPS/TLS?

Короткий ответ: TLS обеспечивает конфиденциальность (шифрование трафика), целостность (нельзя незаметно изменить) и аутентичность сервера (сертификат). Защищает от перехвата и MITM-атак.

Подробно: Без HTTPS трафик идёт открытым текстом — провайдер,公 Wi-Fi, любой на пути может читать пароли, cookie, данные и подменять контент. TLS:

  1. Шифрует — нельзя прочитать перехваченное.
  2. Целостность — нельзя подменить пакеты незаметно.
  3. Аутентичность — сертификат, подписанный CA, подтверждает, что вы общаетесь с настоящим сервером, а не с прокладкой.

MITM (Man-in-the-Middle) — атакующий встаёт между клиентом и сервером, читает/меняет трафик. TLS+валидный сертификат не даёт это сделать незаметно (клиент увидит ошибку сертификата).

⚠️ Ловушка: HTTPS защищает данные в пути, но не от XSS, SQLi, утечки БД или плохой авторизации. «У нас HTTPS, значит безопасно» — заблуждение. Также флаг cookie Secure обязателен, иначе cookie уйдёт и по HTTP.

21

Что такое OWASP Top 10?

Короткий ответ: Список 10 наиболее критичных рисков веб-безопасности от OWASP, обновляемый периодически. Это базовый чек-лист, что проверять.

Подробно (OWASP Top 10, версия 2021, ключевые):

  1. Broken Access Control — самый частый: IDOR, обход проверок прав, повышение привилегий.
  2. Cryptographic Failures — слабое/отсутствующее шифрование, пароли в открытом виде, данные по HTTP.
  3. Injection — SQLi, command injection, LDAP injection (XSS тоже относят сюда).
  4. Insecure Design — изъяны на уровне архитектуры, отсутствие threat modeling.
  5. Security Misconfiguration — дефолтные пароли, открытые админки, лишние заголовки/фичи, неверный CORS.
  6. Vulnerable and Outdated Components — устаревшие зависимости с известными CVE.
  7. Identification and Authentication Failures — слабые пароли, отсутствие MFA, плохие сессии.
  8. Software and Data Integrity Failures — небезопасные обновления, десериализация, CI/CD-цепочка.
  9. Security Logging and Monitoring Failures — нет логов/алертов на атаки.
  10. Server-Side Request Forgery (SSRF) — сервер заставляют ходить на внутренние ресурсы.

⚠️ Ловушка: Broken Access Control — №1, но именно его чаще всего недооценивают, полагаясь на «фронт не покажет кнопку». Авторизацию проверяет сервер на каждом запросе.

22

SQL injection — как работает и как защититься?

Короткий ответ: Атака, где ввод пользователя попадает в 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.

23

XSS — виды и защита?

Короткий ответ: 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-скрипты.
  • HttpOnly cookie — JS не прочитает токен (снижает кражу).
  • Избегать innerHTML/dangerouslySetInnerHTML/eval с пользовательскими данными; санитизировать HTML (DOMPurify).

⚠️ Ловушка: Экранировать нужно по контексту вывода, а не «на входе». Одна и та же строка безопасна в тексте HTML, но опасна внутри <script> или атрибута href="javascript:...". Слепая фильтрация на входе ломает данные и не закрывает все контексты.

24

CSRF — как работает атака и защита?

Короткий ответ: 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-навигациях.

25

CORS и same-origin policy?

Короткий ответ: 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.com
    • Access-Control-Allow-Methods: GET, POST
    • Access-Control-Allow-Headers: Authorization, Content-Type
    • Access-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?

Короткий ответ: RBAC — права через роли (admin, editor). ABAC — права через атрибуты (отдел, время, владелец). Scopes — гранулярные разрешения токена. Least privilege — давать минимально необходимое.

Подробно:

  • RBAC (Role-Based) — пользователю назначают роли, ролям — права. Просто, но грубо при сложных правилах.
  • ABAC (Attribute-Based) — решение по атрибутам субъекта, ресурса и контекста: «менеджер может видеть документ, если он автор ИЛИ из того же отдела И рабочее время». Гибко, сложнее в поддержке.
  • Scopes — в OAuth/токенах: что разрешено токену (read:orders, write:profile).
  • Principle of Least Privilege — каждый компонент/пользователь получает только тот доступ, что строго нужен. Меньше прав — меньше ущерб при компрометации.

⚠️ Ловушка: Авторизацию надо проверять на сервере на каждом запросе и на уровне объекта (этот пользователь имеет право на ЭТУ запись?), а не только «у роли есть доступ к эндпоинту». Иначе — IDOR. Скрытие кнопки на фронте — не авторизация.

27

Rate limiting и защита от brute force?

Короткий ответ: Ограничение числа запросов за интервал (по 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 + мониторинг, чем глухая блокировка. И не раскрывайте, существует ли логин («неверный логин или пароль» — единое сообщение).

28

Secrets management — как хранить секреты?

Короткий ответ: Никогда не хранить секреты (ключи, пароли БД, токены) в коде/репозитории. Использовать переменные окружения, а лучше — секрет-менеджеры (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)?

Короткий ответ: 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 режим), иначе сломаете легитимные скрипты.

30

IDOR — Insecure Direct Object Reference?

Короткий ответ: Уязвимость, когда приложение даёт доступ к объекту по его идентификатору без проверки, что у пользователя есть право на ЭТОТ объект. Подвид 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 не заменяет проверку авторизации: ссылка может утечь, и доступ всё равно должен проверяться.

31

Mass assignment?

Короткий ответ: Уязвимость, когда приложение слепо маппит все поля из тела запроса в объект модели, позволяя пользователю задать поля, которые он не должен (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 и сущности.

32

2FA, MFA, TOTP?

Короткий ответ: 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

Почему нельзя хранить пароли в открытом виде и зачем медленный хеш?

Короткий ответ: При утечке БД открытые пароли мгновенно компрометируют всех (и другие сайты — люди переиспользуют пароли). Хеш необратим. Медленный хеш делает массовый перебор экономически нецелесообразным.

Подробно: Даже сотрудники не должны видеть пароли. Хранят необратимый хеш — при логине хешируют введённое и сравнивают. Но быстрый хеш (SHA-256) перебирается миллиардами в секунду на GPU. Медленный (argon2/bcrypt) с настраиваемым cost замедляет каждую попытку в тысячи раз ⇒ перебор украденной базы становится непрактичным. Соль убирает rainbow tables и одинаковость хешей.

⚠️ Ловушка: «Зашифрую пароли AES» — плохо: шифрование обратимо, и при утечке ключа все пароли вскрываются. Пароли именно хешируют, а не шифруют.

35

Чем XSS опаснее CSRF?

Короткий ответ: XSS исполняет произвольный код атакующего в браузере жертвы — он может всё, что может пользователь, читать токены, обходить CSRF-токены, кейлоггить. CSRF лишь заставляет выполнить конкретное предугаданное действие вслепую.

Подробно: При CSRF атакующий не видит ответ и ограничен заранее известными запросами; защищается SameSite/CSRF-токеном. При XSS код выполняется в контексте сайта: читает DOM, ответы, локальные токены, считывает и подставляет CSRF-токен из страницы, делает любые аутентифицированные запросы. То есть XSS обходит CSRF-защиту. Поэтому XSS — фундаментально опаснее.

⚠️ Ловушка: Защита от CSRF (CSRF-токены) не помогает против XSS — скрипт на странице сам прочитает этот токен. Сначала закрывают XSS.

36

Что значит «не доверяй клиенту»?

Короткий ответ: Любые данные и проверки на клиенте (браузер, мобильное приложение) могут быть подделаны. Все проверки безопасности — валидация, авторизация, лимиты — должны дублироваться и быть авторитетными на сервере.

Подробно: Клиент полностью под контролем пользователя: можно изменить JS, отправить запрос через curl/Postman, подменить заголовки, цены, id, скрытые поля, обойти валидацию формы. Поэтому:

  • Валидация на фронте — только UX, серверная — обязательна.
  • Авторизация — на сервере на каждом запросе и каждом объекте (не «скрыли кнопку»).
  • Цены, скидки, права, количество — пересчитывать/проверять на сервере, не верить значениям из запроса (см. mass assignment).

⚠️ Ловушка: Скрытое поле, disabled-кнопка, проверка только на фронте, «секретный» эндпоинт без авторизации — всё это обходится тривиально. Сервер — единственная граница доверия.

Источники

Источники и редакционная политика

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

От чтения к воспроизведению

Отрепетируйте полный цикл интервью.

RecallDeck возвращает сложные темы по расписанию и помогает удерживать в памяти язык, SQL, архитектуру и поведенческие истории.

Начать подготовку

Продолжить подготовку

Библиотека собеседований RecallDeck

Подробные русские ответы, разборы этапов найма и планы подготовки для российского IT-рынка.

RSS