Куда помещать пароль в HTTP запросе, чтобы он был зашифрован и не был виден сниферу
Что проверяют
Понимаете ли вы, что от сниффера защищает не место в запросе, а TLS, и что место при этом всё равно важно, но по другой причине. Следом спрашивают: видит ли перехватчик URL при HTTPS и чем опасна строка запроса.
Как отвечать
Главная мысль: при HTTPS шифруется весь HTTP-запрос целиком: метод, путь, строка запроса, заголовки и тело. Сниффер в сети видит IP-адреса, порт, объём и время трафика и имя домена в SNI, если не включён Encrypted Client Hello. Без TLS пароль читается откуда угодно, хоть из тела, хоть из заголовка.
Место в запросе важно для утечек за пределами канала:
- строка запроса: плохо. URL оседает в логах доступа nginx и балансировщика, в истории браузера, в заголовке
Referer; - тело
POST: стандартный вариант для логина, JSON илиapplication/x-www-form-urlencoded; - заголовок
Authorization: для Basic Auth. Base64 в нём это кодирование, а не шифрование.
Что сделать на стороне Go:
- TLS:
http.ListenAndServeTLSили терминация на reverse proxy. Вtls.ConfigвыставитьMinVersion: tls.VersionTLS12, лучше 1.3, и отдавать заголовокStrict-Transport-Security; - клиент: никогда не ставить
InsecureSkipVerify: trueв рабочем коде, иначе подменённый сертификат пройдёт проверку; - логи: middleware логирования не пишет тело запросов на эндпоинтах авторизации и маскирует
Authorization; - хранение: пароль в базе только хэшем через
golang.org/x/crypto/bcryptилиargon2. После входа клиент работает с токеном или сессией, а не шлёт пароль каждый раз.
Где спотыкаются
Утверждают, что в заголовке пароль «безопаснее», чем в теле. Для сниффера разницы нет: при HTTPS зашифровано и то и другое, без HTTPS открыто и то и другое.
Предлагают хэшировать пароль на клиенте вместо TLS. Тогда хэш сам становится паролем, и перехватчик просто отправит его повторно.
Отключают проверку сертификата «на время отладки» через InsecureSkipVerify и забывают вернуть. Шифрование формально остаётся, но от атаки посредника оно уже не защищает.