Le ven. 27 févr. 2026 à 10:13, Jérémy Lal <[email protected]> a écrit :
> > > Le ven. 27 févr. 2026 à 09:55, Gabriel Corona <[email protected]> a > écrit : > >> In addition to the issue discussed by OP, using $http_host could >> possibly introduce vulnerabilities to HTTP Host ambiguity attacks. >> >> Debian's /etc/nginx/proxy_param uses the following line: >> >> proxy_set_header Host $http_host; >> >> This configuration is not consistent which what is recommended by >> NGINX documentation [1]: >> >> proxy_set_header Host $host; >> >> Note that the nginx-snippets package contains a >> common-proxy-pass-headers.conf file which includes a correct >> configuration: >> >> proxy_set_header Host $host; >> proxy_set_header X-Forwarded-Host $host; >> >> An attacker can use a HTTP/1 request with ambiguous hosts: >> >> GET http://host1/ HTTP/1.1 >> User-Agent: UA >> Host: host2 >> >> This type of request is accepted by NGINX when using HTTP/1 only. >> >> In this case, with "proxy_set_header Host $http_host;": >> >> * server name "host1" is used for virtual host dispatching in NGINX; >> * server name "host2" is passed to upstream HTTP server. >> >> If NGINX is used to apply security restrictions/filtering to a >> multi-host/multi-tenant backend application, this could be used to apply >> the NGINX rules of "host1" while targeting upstream "host2. >> >> For example: >> >> * if NGINX is applying some IP adresse restriction to host2, >> the attacker can target host2 without these restrictions [a]; >> * if host1 and host2 are using different mTLS configuration, >> the attackers could use their mTLS keypair for host1 and >> target host2; >> * if the upstream server uses the host/authority (probably a bad >> idea) to build absolute URLs, an attacker could use >> host-ambiguous requests to generate links to malicious servers >> (especially with cache poisoning). >> >> I reached to NGINX to discuss about this potential host ambiguity and >> I suggested using a "safer" logic such as: >> >> * overriding the Host header with the request line authority if present >> (same as Apacher httpd, Traefik and Caddy); >> * rejecting host-ambiguous requests entirely (same as NGINX in HTTP/2, >> HA Proxy). >> >> Their assessment is that this is a configuration error i.e. you >> should use $host and not $http_host. >> >> More generally, other usages of $http_host introduce a host ambiguity >> issue which might have a security impact (eg. for in proxy_pass, >> access_log, etc.). >> >> [a]: >> >> server { >> listen 443 ssl; >> server_name host1; >> ssl_certificate /etc/nginx/ssl/host1.crt; >> ssl_certificate_key /etc/nginx/ssl/host1.key; >> location / { >> proxy_pass http://backend; >> include proxy_params; >> } >> } >> server { >> listen 443 ssl; >> server_name host2; >> ssl_certificate /etc/nginx/ssl/host2.crt; >> ssl_certificate_key /etc/nginx/ssl/host2.key; >> location / { >> allow 10.0.0.0/8; >> allow 192.168.0.0/16; >> allow 127.0.0.1/8; >> deny all; >> proxy_pass http://backend; >> include proxy_params; >> } >> } >> >> [b]: >> >> server { >> listen 443 ssl; >> server_name host1; >> ssl_certificate /etc/nginx/ssl/host1.crt; >> ssl_certificate_key /etc/nginx/ssl/host1.key; >> ssl_client_certificate /etc/nginx/ssl/ca-host1.crt; >> ssl_verify_client on; >> ssl_verify_depth 2; >> location / { >> proxy_pass http://backend; >> include proxy_params; >> } >> } >> server { >> listen 443 ssl; >> server_name host2; >> ssl_certificate /etc/nginx/ssl/host2.crt; >> ssl_certificate_key /etc/nginx/ssl/host2.key; >> ssl_client_certificate /etc/nginx/ssl/ca-host1.crt; >> ssl_verify_client on; >> ssl_verify_depth 2; >> location / { >> proxy_pass http://backend; >> include proxy_params; >> } >> } >> >> === Potential fixes/mitigation >> >> Mitigation 0: use the hardcoded expected hostname instead of `$http_host`. >> >> proxy_set_header Host "www.example.com"; >> proxy_set_header X-Forwarded-Host "www.example.com"; >> >> Downside: not suitable for NGINX proxy_params. >> >> Mitigation 1: use $host instead of $http_host: >> >> proxy_set_header Host $host; >> proxy_set_header X-Forwarded-Host $host; >> >> Downside: this not not include the port information which could >> be a breaking change for some applications. > > Mitigation 1: use $host$is_request_port$request_port instead of $http_host: >> >> proxy_set_header Host $host$is_request_port$request_port; >> proxy_set_header X-Forwarded-Host $host$is_request_port$request_port; >> >> Downside: only available since NGINX 1.29.3 (not in trixie). > > >> Note: I think the $request_port could be spoofed anyway. > > >> Mitigation 2: use NGINX directive to reject ambiguous (malicious) >> requests. >> >> Either (does not work when using ports): >> >> if ($host != $http_host) { >> return 421 "Ambiguous host"; >> } >> >> or: >> >> if ($http_host != "$host$is_request_port$request_port") { >> return 421 "Ambiguous host"; >> } >> >> === Q: Should NGINX accept or rejects HTTP requests with host ambiguity? >> >> Host-ambiguous requests are accepted by NGINX based on RFC 9112 section >> 3.2.2 [2]: >> >> > When an origin server receives a request with an absolute-form of >> > request-target, the origin server MUST ignore the received Host >> > header field (if any) and instead use the host information of >> > the request-target. Note that if the request-target does not >> > have an authority component, an empty Host header field >> > will be sent in this case. >> >> NGINX is acting as a reverse proxy and is therefore [3] considered >> an origin server in this context. >> >> On the other hand, I would argue that rejecting the request would make >> sense as per section 3.2 [4]: >> >> > A client MUST send a Host header field (Section 7.2 of [HTTP]) >> > in all HTTP/1.1 request messages. If the target URI includes an >> > authority component, then a client MUST send a field value for Host >> > that is identical to that authority component, excluding any >> > userinfo subcomponent and its "@" delimiter (Section 4.2 of [HTTP]). >> > > It's an nginx feature, so we can't really get in its way. > > We should limit ourselves to fixing proxy_params, and that's not going to > be backported to trixie so I suggest to just wait for nginx 1.30 to be in > debian, > and then use $is_request_port. > Also I see very odd behavior of http3 with nginx 1.26 (some HTTP3 connections just hang for no reasons). So until the experimental "tag" is removed from the documentation, I strongly suggest to not use nginx quic, except for development.

