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.


Other HTTP servers, do not work like this. For example:
>
> * Apache HTTPD appears to ignore the incoming Host header field
>    entirely when the authority is present in the request line;
> * ditto for Traefik;
> * ditto for Caddy
> * HA proxy triggers a HTTP 400 when receiving a host-ambiguous request;
> * ditto for uWSGI.
>
> For HTTP/2, the expected behavior is clearly to reject the request
> when both "Host" and ":authority" are used but are not consistent
> as per RFC 9113 section 9.3.1 [5] (HTTP/2):
>
>  > A server SHOULD treat a request as malformed if it contains a
>  > Host header field that identifies an entity that differs
>  > from the entity in the ":authority" pseudo-header field.
>
> Ditto for HTTP/3, as per RFC 9114 section 4.3.1 [6] as far as
> I understand:
>
>  > If both fields are present, they MUST contain the same value.
>  >
>  > [..]
>  >
>  > An HTTP request that omits mandatory pseudo-header fields or
>  > contains invalid values for those pseudo-header fields is
>  > malformed.
>
> [1] https://docs.nginx.com/nginx/admin-guide/web-server/reverse-proxy/
> [2] https://www.rfc-editor.org/rfc/rfc9112.html#name-absolute-form
> [3] https://www.rfc-editor.org/rfc/rfc9110.html#name-intermediaries
> [4] https://www.rfc-editor.org/rfc/rfc9112.html#section-3.2
> [5] https://www.rfc-editor.org/rfc/rfc9113.html#section-8.3.1
> [6] https://www.rfc-editor.org/rfc/rfc9114.html#section-4.3.1
> _______________________________________________
> Pkg-nginx-maintainers mailing list
> [email protected]
>
> https://alioth-lists.debian.net/cgi-bin/mailman/listinfo/pkg-nginx-maintainers
>

Reply via email to