Skip to content

Commit

Permalink
Ignore obviously malformed host headers when constructing a ServerR…
Browse files Browse the repository at this point in the history
…equest

I opted to ignore the `host` header instead of throwing an Exception to not
introduce a remotely triggerable exception.

Signed-off-by: Tim Düsterhus <duesterhus@woltlab.com>
  • Loading branch information
TimWolla committed Jul 1, 2022
1 parent 58e4f98 commit d2f2859
Show file tree
Hide file tree
Showing 2 changed files with 45 additions and 1 deletion.
10 changes: 9 additions & 1 deletion src/ServerRequestFactory.php
Expand Up @@ -168,7 +168,15 @@ private static function marshalHostAndPort(array $server, array $headers) : arra

$host = self::getHeaderFromArray('host', $headers, false);
if ($host !== false) {
return self::marshalHostAndPortFromHeader($host);
// Ignore obviously malformed host headers:
// - Whitespace is invalid within a hostname and break the URI representation within HTTP.
// non-printable characters other than SPACE and TAB are already rejected by HeaderSecurity.
// - A comma indicates that multiple host headers have been sent which is not legal
// and might be used in an attack where a load balancer sees a different host header
// than Diactoros.
if (! \preg_match('/[\\t ,]/', $host)) {
return self::marshalHostAndPortFromHeader($host);
}
}

if (! isset($server['SERVER_NAME'])) {
Expand Down
36 changes: 36 additions & 0 deletions test/ServerRequestFactoryTest.php
Expand Up @@ -786,4 +786,40 @@ public function testHonorsHostHeaderOverServerNameWhenMarshalingUrl(): void
$uri = $request->getUri();
$this->assertSame('example.com', $uri->getHost());
}

/**
* @psalm-return iterable<string, array{
* 0: string
* }>
*/
public function invalidHostHeaders(): iterable
{
return [
'comma' => ['example.com,example.net'],
'space' => ['example com'],
'tab' => ["example\tcom"],
];
}

/**
* @dataProvider invalidHostHeaders
*/
public function testRejectsDuplicatedHostHeader(string $host): void
{
$server = [
'HTTP_HOST' => $host,
];

$request = ServerRequestFactory::fromGlobals(
$server,
null,
null,
null,
null,
new DoNotFilter()
);

$uri = $request->getUri();
$this->assertSame('', $uri->getHost());
}
}

0 comments on commit d2f2859

Please sign in to comment.