# Host Injection Analyzer PRO
|Category||Severity||Time To Fix|
|🛡️ Security||Major||5 minutes|
This analyzer ensures that your application is not vulnerable to host injection attacks. In this attack, the attacker can change the host of a signed URL using the
X-Forwarded-Host or the
Host header. This would allow an attacker to generate a malicious password reset email with a link to a website controlled by the attacker.
Host injection attacks can happen via either the
X-Forwarded-Host header or the
- If your application is behind a load balancer or reverse proxy and it does not set trusted hosts, it will be exposed to host injection attacks via the
X-Forwarded-Hostheader. If you have already set the
X-Forwarded-Hostheader at your reverse proxy level, you may ignore this analyzer.
- If your web server configuration is insecure, it may allow host injection attacks via the
HostHeader. This may happen if you use server name wildcards or do not have catch-all server configurations to catch all requests with unrecognized Host headers.
This video (opens new window) shows a live demo of the vulnerability. Note that password reset poisoning is just one of the possible attacks. Other attacks that arise from host header injection include web cache poisoning, bypassing authentication, SSRF and virtual host brute-forcing. You may learn more about this here (opens new window).
# Easy Way To Confirm
To confirm that this is an issue, you can use
curl to fire the following two requests to your application:
curl https://myapp.com -H "Host: evil.com" curl https://myapp.com -H "X-Forwarded-Host: evil.com"
If you see
evil.com in any of the response headers (e.g. Location header) or in any of the response body URLs, then you're vulnerable.
# How To Fix Host Header Injection
Host header injection attacks, you must have a secure web server configuration.
Make sure to configure a catch-all server block (Nginx) or VirtualHost (Apache) to catch all requests with unrecognized Host headers, specify non-wildcard server names and turn on the
UseCanonicalName directive (for Apache).
In case you do not have control over your web server configuration, you may add the
TrustHosts middleware to your global middleware.
If you use reverse proxy CDNs such as Cloudflare, they should automatically take care of this for you.
# How To Fix X-Forwarded-Host Header Injection
# Option 1: Add the TrustHosts Middleware
Simply add the
TrustHosts middleware to your global middleware as indicated below:
/** * The application's global HTTP middleware stack. * * These middleware are run during every request to your application. * * @var array */ protected $middleware = [ \App\Http\Middleware\TrustHosts::class, \App\Http\Middleware\TrustProxies::class, \Fruitcake\Cors\HandleCors::class, \App\Http\Middleware\PreventRequestsDuringMaintenance::class, \Illuminate\Foundation\Http\Middleware\ValidatePostSize::class, \App\Http\Middleware\TrimStrings::class, \Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull::class, ];
# Option 2: Whitelist Your TrustedProxy Headers
By default, the
TrustProxies middleware whitelists all headers including
X-Forwarded-Host. You may specifically set the whitelist headers to only
X-Forwarded-For in your
App\Http\Middleware\TrustProxies class, so that even if the attacker sets the
X-Forwarded-Host header, it will not be trusted by your application:
/** * The headers that should be used to detect proxies. * * @var int */ protected $headers = Request::HEADER_X_FORWARDED_FOR;
# Option 3: Explicitly Set All X-Forwarded Headers At Your Reverse Proxy
You may also explicitly set all
X-Forwarded-* headers at your reverse proxy so that they override any headers set by a possible attacker. To do this in Nginx, you can add the following directives:
proxy_set_header X-Forwarded-Proto $scheme; proxy_set_header X-Forwarded-Host $host; proxy_set_header X-Forwarded-Port $server_port;
# Option 4: Replace IP Address At Your Application Web Server(s)
If you are using Nginx, you may replace the remote IP address directly from the X-Forwarded-For header, without the need to setup trusted proxies in Laravel:
Make sure you set this at your application web server(s) and not at your load balancer/reverse proxy. This directive replaces the remote IP address with the
X-Forwarded-For IP address that the web server receives from the load balancer/reverse proxy.
You may also add a
set_real_ip_from directive so that it only trusts valid load balancers/reverse proxies:
The IP address CIDR added above should be replaced with that of your load balancers or reverse proxies (assuming they are in the same VPN). This may not be required if you have a firewall rule setup to only allow incoming traffic to your web server(s) from your load balancer/reverse proxy VPN.
After you add the directives above, remove both the
This analyzer currently only passes with Option 1 and 4. So, if you are solving the issue with Option 2 or 3, you may ignore this analyzer.
# Skip Condition
This analyzer is skipped if your application does not use trusted proxies.
- Host Injection Demo on A Laravel App (opens new window)
- Laravel Documentation on Trusted Proxies (opens new window)
- Discussion on Host Injection on the Laravel Repo (opens new window)
- Introduction to Host Header Injection Attacks (opens new window)
- Nginx Documentation on the Real IP Module (opens new window)
- Nginx Documentation on the Proxy Module (opens new window)