При использовании HTTPS (TLS+SNI) мы отправляем доменное имя 2 раза:
- В SNI для получения сертификата.
- Когда сервер расшифрует полученные данные и прочтет в секции header
HOST
.
Тут у нас возникает Host Header Injection уязвимость.
Как воспроизвести уязвимость
Добавим в index.php код с выводом $_SERVER
var_dump(
$_SERVER['HTTP_HOST']
);
Выполним Host Header Injection через curl команду
curl -v -H "Host: hacker-yoda.com" wp-yoda.com
Если наш сайт подвержен этой уязвимости, в консоли в ответе сайта мы увидим (string) hacker-yoda.com
.
Если вы используете
$_SERVER['HTTP_HOST']
без обработки для формирования ссылок, редиректов, итд это может быть большой проблемой.
В WordPress само ядро и многие плагины полагаются на
$_SERVER['HTTP_HOST']
.
Защита от Host Header Injection
- Нет ничего лучше чем правильная настройка сервера. Вы можете проксировать в PHP-FPM домен указанный на сервере строкой или в
server_name
.
server {
listen 443 ssl;
server_name example.com;
ssl_certificate /path/to/example.com.crt;
ssl_certificate_key /path/to/example.com.key;
root /path/to/your/webroot;
index index.php index.html index.htm;
location ~ \.php$ {
try_files $uri =404;
fastcgi_pass unix:/var/run/php/php7.4-fpm.sock;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param HTTP_HOST $server_name; # Insatll HTTP_HOST as a value of server_name
include fastcgi_params;
}
location / {
try_files $uri $uri/ =404;
}
}
или делать проверку что server_name
= host
map $ssl_server_name $expected_host {
hostnames;
example.com example.com;
another-example.com another-example.com;
}
server {
listen 443 ssl;
server_name example.com another-example.com;
if ($host != $expected_host) {
return 444;
}
# Общая конфигурация...
}
Одна из этих конфигураций поможет защититься от атак Host Header Injection, гарантируя, что имя хоста в TLS-рукопожатии (SNI) соответствует ожидаемому заголовку Host
в HTTP-запросе.
2. Установить Load-Balancer впереди Nginx/Apache. Это позволит делать проверку сертификатов сделать на Load-Balancer, а дальше отправлять данные по HTTP (незашифрованно) в Nginx по внутрнней сети.
3. Не использовать `$_SERVER[‘HTTP_HOST’]`. Вместо него использовать env variables с заданными вами строками.
К счастью подавляющее большинство хостинговых компаний имеют проверку на стороне сервера. Но с кастомными серверами лучше удосторовериться, что вы настроили все верно.