I am willing to prevent host header attack in my laravel 9 app. I am using this command in terminal to test for that attack - curl http://127.0.0.1:8000 -H "Host: evil.com"
.
After searching on internet i have enabled this \App\Http\Middleware\TrustHosts::class
middleware in kernel.php
file.
Even i have created my own middleware to check for host header like this
<?php
namespace App\Http\Middleware;
use Closure;
class HostHeaderValidationMiddleware
{
public function handle($request, Closure $next)
{
$expectedDomain = '127.0.0.1';
// echo $_SERVER['HTTP_HOST'];
// echo "<br>";
// echo $_SERVER['SERVER_NAME'];exit;
// Validate and sanitize the host header
if ($request->getHost() !== $expectedDomain || $_SERVER['SERVER_NAME'] !== $expectedDomain) {
abort(400, 'Invalid request.');
}
// Validating referer header
$referer = $request->headers->get('Referer');
if ($referer && parse_url($referer, PHP_URL_HOST) !== $expectedDomain) {
abort(400, 'Invalid Referer header.');
}
return $next($request);
}
}
But after running this command it is not even going into this middleware it is giving this output in terminal
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<meta http-equiv="refresh" content="0;url='http://evil.com/login'" />
<title>Redirecting to http://evil.com/login</title>
</head>
<body>
Redirecting to <a href="http://evil.com/login">http://evil.com/login</a>.
</body>
</html>
Is ther any other way to prevent host header attack in Laravel or PHP
You can skip your own middleware and use the laravel trusted hosts middleware (The one shipped with laravel which you enabled).
Make sure that in the middleware you have defined your hosts, something like this:
public function hosts(): array
{
return [
'localhost', '127.0.0.1',
$this->allSubdomainsOfApplicationUrl(),
];
}
Alternativley you can skip adding localhost and use the defaults like this:
public function hosts(): array
{
return [
$this->allSubdomainsOfApplicationUrl(),
];
}
In that case you need to make sure that APP_URL
in your .env
file is correct. Then only requests to the APP_URL
host (and it's subdomains) are allowed.
Note: That your port 8000 suggests you are running laravel with php artisan serve
. If your app is local
laravel will skip the trusted hosts checks. (If you look into the Illuminate\Http\Middleware\TrustHosts
class you will see this check:
/**
* Determine if the application should specify trusted hosts.
*
* @return bool
*/
protected function shouldSpecifyTrustedHosts()
{
return ! $this->app->environment('local') &&
! $this->app->runningUnitTests();
}
So make sure in your .env
file APP_ENV
is NOT set to local
. Set it to something like production
instead:
APP_ENV=production
When you have followed my instructions above curl http://127.0.0.1:8000 -H "Host: evil.com"
should return a 404 (Not Found) status code and page