Вопрос или проблема
Изучаем, можем ли мы применять Basic auth в сервисе только через установку заголовка Authorization, и, следовательно, препятствовать обмену ссылками с форматом username:password@url. Можно ли это сделать, например, в Nginx или современные браузеры и клиенты, такие как curl, автоматически перемещают имя пользователя и пароль в заголовок Authorization?
Отправка запроса на http://user:pass@localhost/test со следующим конфигом Nginx показывает, что $host
всегда является просто ‘localhost’, а не user:pass@localhost. $hostname
всегда имеет некоторое хешированное значение. Есть ли другие переменные, которые я должен попробовать?
limit_req_zone $remote_user zone=one:10m rate=1r/s;
limit_req_status 429;
server {
listen 80;
server_name localhost;
set $deny '1';
if ($http_authorization) { set $deny ''; }
if ($deny) { return 403; }
location /test {
add_header Content-Type application/json;
return 200 '{ "host": $host, "request_uri": $request_uri, "hostname": $hostname }';
}
location / {
root /usr/share/nginx/html;
index index.html index.htm;
limit_req zone=one;
proxy_pass http://localhost:8080;
}
}
server {
listen 8080;
location / {
return 200;
}
}
Ответ или решение
Вопрос о возможности блокировки синтаксиса username:password@ в Basic Authentication на уровне Nginx имеет сложное решение, которое требует понимания того, как данный механизм работает в современном веб-серфинге и запросах. Важно понимать, что HTTP Basic Authentication — это метод передачи пользовательских данных в заголовке HTTP-запроса, который поддерживается большинством веб-серверов и клиентов, включая Nginx и curl. Однако использование формата URL с креденциалами username:password@url
считается устаревшим и небезопасным.
Теория:
Синтаксис username:password@
в URL был популярен некоторое время назад, однако в современных веб-браузерах и клиентах произошло множество изменений в области безопасности. На данный момент, большинство современных браузеров не поддерживают передачу авторизационных данных через URL-адрес из соображений безопасности, а многие сервера или прокси-серверы, такие как Nginx, даже не интерпретируют эту часть в URI как часть хоста. Вместо этого данные авторизации, если они вообще поддерживаются, обычно перемещаются в заголовок Authorization
автоматически.
Диаграмма обработки в Nginx также структурирована так, что он интерпретирует часть URL в username:password@host
лишь как информацию о хосте. Таким образом, сервер игнорирует непосредственно сам синтаксис авторизации при разборе сетевых запросов.
Пример:
В описанной конфигурации Nginx используются проверка заголовка Authorization
и ограничения запросов, исходя из значения переменной $remote_user
. Однако $remote_user
устанавливается только в случае успешной передачи данных аутентификации через заголовок Authorization
, который в случае заданного формата в URL-адресе не передается. Сам по себе формат username:password@host
не оказывает влияния на то, что Nginx внутри видит как localhost
, или на то, что $hostname
остается не раскрытым в осмысленное значение.
limit_req_zone $remote_user zone=one:10m rate=1r/s;
limit_req_status 429;
server {
listen 80;
server_name localhost;
set $deny '1';
if ($http_authorization) { set $deny ''; }
if ($deny) { return 403; }
location /test {
add_header Content-Type application/json;
return 200 '{ "host": $host, "request_uri": $request_uri, "hostname": $hostname }';
}
location / {
root /usr/share/nginx/html;
index index.html index.htm;
limit_req zone=one;
proxy_pass http://localhost:8080;
}
}
В приведенной конфигурации, механизм block запроса на основе $http_authorization
гарантирует, что любые запросы (где этот заголовок не участвует) получают статус 403. Однако полностью избежать открытия в формате username:password@host
возможно только вероятностными методами, нежели обходными.
Применение:
Чтобы предотвратить использование устаревшего синтаксиса логина через URL на уровне Nginx, вы можете предпринять несколько шагов:
-
Общая практика безопасности: Отключите любую аутентификацию через URL на клиентском уровне и используйте только HTTPS вместе с проверенными методами аутентификации через заголовки, например, Bearer Tokens или OAuth.
-
Редакторские рекомендации: Настройка такого, чтобы прокси-сервисы и загрузочные библиотеки перенаправляли и блокировали попытки передачи username:password через били=False в URL.
-
Nginx Module Customization: Исследуйте возможность использования модулей или сторонних скриптов для Nginx, которые бы смогли анализировать полный URI, включая данные до хоста, и оценивать попытки небезопасных запросов.
-
Мониторинг и Ведение Логов: Для более детальной информации о неудачной попытке аутентификации через URI-данные, можно организовать соответствующий мониторинг логов и указание Audit использования переменных состояния.
В свете текущих изменений в практике веб-безопасности, рекомендуется полностью отказаться от использования username:password@ в URL и переводить все авторизационные запросы к передаче через безопасные заголовки HTTP. Это не только улучшает безопасность, но и соответствует настоящему веб-серфингу и методам веб-разработки.