Navigation Menu

Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Ignore obviously malformed host headers when constructing a ServerRequest #97

Closed
wants to merge 2 commits into from

Conversation

TimWolla
Copy link
Contributor

@TimWolla TimWolla commented Jul 1, 2022

Q A
Documentation no
Bugfix no
BC Break no
New Feature yes
RFC no
QA no

Description

The comment within the code should be self-explanatory. This adds some very basic checks to the host header as a hardening measure.

Signed-off-by: Tim Düsterhus <duesterhus@woltlab.com>
…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>
Copy link
Member

@weierophinney weierophinney left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Quick question: does the Uri class not already disallow these values? Or is the change here primarily to just reject the Host header as a source for creating a Uri instance if it is malformed?

In other words, I'm wondering if we don't already get an exception that occurs for malformed Host headers.

@TimWolla
Copy link
Contributor Author

TimWolla commented Jul 1, 2022

Quick question: does the Uri class not already disallow these values?

No, the Uri class accepts arbitrary garbage as the host:

public function withHost($host) : UriInterface
{
if (! is_string($host)) {
throw new Exception\InvalidArgumentException(sprintf(
'%s expects a string argument; received %s',
__METHOD__,
is_object($host) ? get_class($host) : gettype($host)
));
}
if ($host === $this->host) {
// Do nothing if no change was made.
return $this;
}
$new = clone $this;
$new->host = strtolower($host);
return $new;
}

In other words, I'm wondering if we don't already get an exception that occurs for malformed Host headers.

No, we don't. We likely should, but that would probably be a BC break. With this PR I wanted to add some minimally invasive checks to reject/ignore the most egregious violations that might actually cause harm, as the host header is possibly untrusted.

@weierophinney weierophinney added the Bug Something isn't working label Jul 1, 2022
src/ServerRequestFactory.php Show resolved Hide resolved
return [
'comma' => ['example.com,example.net'],
'space' => ['example com'],
'tab' => ["example\tcom"],
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add another case here for entries containing newlines.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These are already rejected by HeaderSecurity and thus the request completely fails to construct. See: https://github.com/laminas/laminas-diactoros/runs/7151517319?check_suite_focus=true

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should the usage.md be updated to explain that ServerRequestFactory may throw based on user input and any exceptions need to be gracefully handled: https://github.com/laminas/laminas-diactoros/blob/2.12.x/docs/book/v2/usage.md#marshaling-an-incoming-request?

see WoltLab/WCF#4888

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure about it, but this discussion can be deferred to a different issue

@TimWolla TimWolla force-pushed the validate-host-header branch 2 times, most recently from f3c6243 to d2f2859 Compare July 1, 2022 14:14
@Ocramius
Copy link
Member

Ocramius commented Jul 6, 2022

Should this go against 2.11.x, being a bugfix?

@TimWolla
Copy link
Contributor Author

TimWolla commented Jul 6, 2022

Should this go against 2.11.x, being a bugfix?

This technically has a (tiny) chance for breakage and is intended as a defense in depth measure. The web server / load balancer in front should already prevent those requests from reaching Diactoros. IMO 2.12 is fine.

* @param mixed $default Default value to return if header not found
* @return mixed
* @param T $default Default value to return if header not found
* @return string|T
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice improvement!

@Ocramius Ocramius added this to the 2.12.0 milestone Jul 6, 2022
@Ocramius Ocramius added Enhancement and removed Bug Something isn't working labels Jul 6, 2022
@Ocramius Ocramius self-assigned this Jul 6, 2022
@Ocramius Ocramius closed this in 54d4682 Jul 6, 2022
@Ocramius
Copy link
Member

Ocramius commented Jul 6, 2022

Rebased + manually merged in 54d4682

That allowed shrinking of the baseline too.

Thanks @TimWolla!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants