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

Invalid host in request fails with Internal Server Error #12

Closed
marc-mabe opened this issue Jan 4, 2022 · 6 comments · Fixed by #13
Closed

Invalid host in request fails with Internal Server Error #12

marc-mabe opened this issue Jan 4, 2022 · 6 comments · Fixed by #13
Assignees
Labels
Bug Something isn't working
Milestone

Comments

@marc-mabe
Copy link

Bug Report

Q A
Version(s) 3.7.0

Summary

Requests with and invalid Host header value end up in 500 Internal Server Error.
As it's not a valid request the response should be 400 Bad Request.
At our company we get an alert for 5xx errors and so we are getting alerted each time someone send invalid requests like this:

[2022-01-04T02:02:50+00:00] [ERR] 500 [GET] https://${ip}/: Laminas\Uri\Exception\InvalidUriPartException: Host "${ip}" is not valid or is not accepted by Laminas\Uri\Http in /app/vendor/laminas/laminas-uri/src/Uri.php:767 Stack trace:
#0 /app/vendor/laminas/laminas-uri/src/Uri.php(339): Laminas\Uri\Uri->setHost()
mezzio/mezzio-router#1 /app/vendor/laminas/laminas-uri/src/Http.php(218): Laminas\Uri\Uri->parse()
mezzio/mezzio-router#2 /app/vendor/laminas/laminas-uri/src/Uri.php(165): Laminas\Uri\Http->parse()
mezzio/mezzio-router#3 /app/vendor/laminas/laminas-http/src/Request.php(204): Laminas\Uri\Uri->__construct()
mezzio/mezzio-router#4 /app/vendor/laminas/laminas-psr7bridge/src/Laminas/Request.php(42): Laminas\Http\Request->setUri()
mezzio/mezzio-router#5 /app/vendor/laminas/laminas-psr7bridge/src/Psr7ServerRequest.php(34): Laminas\Psr7Bridge\Laminas\Request->__construct()
mezzio/mezzio-router#6 /app/vendor/mezzio/mezzio-laminasrouter/src/LaminasRouter.php(85): Laminas\Psr7Bridge\Psr7ServerRequest::toLaminas()
mezzio/mezzio-router#7 /app/vendor/mezzio/mezzio-router/src/Middleware/RouteMiddleware.php(37): Mezzio\Router\LaminasRouter->match()
mezzio/mezzio-router#8 /app/vendor/mezzio/mezzio/src/Middleware/LazyLoadingMiddleware.php(37): Mezzio\Router\Middleware\RouteMiddleware->process()
mezzio/mezzio-router#9 /app/vendor/laminas/laminas-stratigility/src/Next.php(51): Mezzio\Middleware\LazyLoadingMiddleware->process()
mezzio/mezzio-router#10 /app/vendor/mezzio/mezzio-helpers/src/ServerUrlMiddleware.php(30): Laminas\Stratigility\Next->handle()
mezzio/mezzio-router#11 /app/vendor/mezzio/mezzio/src/Middleware/LazyLoadingMiddleware.php(37): Mezzio\Helper\ServerUrlMiddleware->process()
mezzio/mezzio-router#12 /app/vendor/laminas/laminas-stratigility/src/Next.php(51): Mezzio\Middleware\LazyLoadingMiddleware->process()
mezzio/mezzio-router#13 /app/vendor/laminas/laminas-stratigility/src/Middleware/ErrorHandler.php(131): Laminas\Stratigility\Next->handle()
mezzio/mezzio-router#14 /app/vendor/mezzio/mezzio/src/Middleware/LazyLoadingMiddleware.php(37): Laminas\Stratigility\Middleware\ErrorHandler->process()
mezzio/mezzio-router#15 /app/vendor/laminas/laminas-stratigility/src/Next.php(51): Mezzio\Middleware\LazyLoadingMiddleware->process()
mezzio/mezzio-router#16 /app/vendor/laminas/laminas-stratigility/src/MiddlewarePipe.php(76): Laminas\Stratigility\Next->handle()
mezzio/mezzio-router#17 /app/vendor/laminas/laminas-stratigility/src/MiddlewarePipe.php(65): Laminas\Stratigility\MiddlewarePipe->process()
mezzio/mezzio-router#18 /app/vendor/mezzio/mezzio-swoole/src/Event/RequestHandlerRequestListener.php(119): Laminas\Stratigility\MiddlewarePipe->handle()
mezzio/mezzio-router#19 /app/vendor/mezzio/mezzio-swoole/src/Event/EventDispatcher.php(39): Mezzio\Swoole\Event\RequestHandlerRequestListener->__invoke()
mezzio/mezzio-router#20 /app/vendor/mezzio/mezzio-swoole/src/SwooleRequestHandlerRunner.php(135): Mezzio\Swoole\Event\EventDispatcher->dispatch()
mezzio/mezzio-router#21 [internal function]: Mezzio\Swoole\SwooleRequestHandlerRunner->onRequest()
mezzio/mezzio-router#22 /app/vendor/mezzio/mezzio-swoole/src/SwooleRequestHandlerRunner.php(79): Swoole\Server->start()
mezzio/mezzio-router#23 /app/vendor/mezzio/mezzio/src/Application.php(68): Mezzio\Swoole\SwooleRequestHandlerRunner->run()
mezzio/mezzio-router#24 /app/bin/server.php(28): Mezzio\Application->run()
mezzio/mezzio-router#25 /app/bin/server.php(29): {closure}()
#26 {main}

Next Laminas\Http\Exception\InvalidArgumentException: Invalid URI passed as string (https://${ip}/) in /app/vendor/laminas/laminas-http/src/Request.php:206 Stack trace:
#0 /app/vendor/laminas/laminas-psr7bridge/src/Laminas/Request.php(42): Laminas\Http\Request->setUri()
mezzio/mezzio-router#1 /app/vendor/laminas/laminas-psr7bridge/src/Psr7ServerRequest.php(34): Laminas\Psr7Bridge\Laminas\Request->__construct()
mezzio/mezzio-router#2 /app/vendor/mezzio/mezzio-laminasrouter/src/LaminasRouter.php(85): Laminas\Psr7Bridge\Psr7ServerRequest::toLaminas()
mezzio/mezzio-router#3 /app/vendor/mezzio/mezzio-router/src/Middleware/RouteMiddleware.php(37): Mezzio\Router\LaminasRouter->match()
mezzio/mezzio-router#4 /app/vendor/mezzio/mezzio/src/Middleware/LazyLoadingMiddleware.php(37): Mezzio\Router\Middleware\RouteMiddleware->process()
mezzio/mezzio-router#5 /app/vendor/laminas/laminas-stratigility/src/Next.php(51): Mezzio\Middleware\LazyLoadingMiddleware->process()
mezzio/mezzio-router#6 /app/vendor/mezzio/mezzio-helpers/src/ServerUrlMiddleware.php(30): Laminas\Stratigility\Next->handle()
mezzio/mezzio-router#7 /app/vendor/mezzio/mezzio/src/Middleware/LazyLoadingMiddleware.php(37): Mezzio\Helper\ServerUrlMiddleware->process()
mezzio/mezzio-router#8 /app/vendor/laminas/laminas-stratigility/src/Next.php(51): Mezzio\Middleware\LazyLoadingMiddleware->process()
mezzio/mezzio-router#9 /app/vendor/laminas/laminas-stratigility/src/Middleware/ErrorHandler.php(131): Laminas\Stratigility\Next->handle()
mezzio/mezzio-router#10 /app/vendor/mezzio/mezzio/src/Middleware/LazyLoadingMiddleware.php(37): Laminas\Stratigility\Middleware\ErrorHandler->process()
mezzio/mezzio-router#11 /app/vendor/laminas/laminas-stratigility/src/Next.php(51): Mezzio\Middleware\LazyLoadingMiddleware->process()
mezzio/mezzio-router#12 /app/vendor/laminas/laminas-stratigility/src/MiddlewarePipe.php(76): Laminas\Stratigility\Next->handle()
mezzio/mezzio-router#13 /app/vendor/laminas/laminas-stratigility/src/MiddlewarePipe.php(65): Laminas\Stratigility\MiddlewarePipe->process()
mezzio/mezzio-router#14 /app/vendor/mezzio/mezzio-swoole/src/Event/RequestHandlerRequestListener.php(119): Laminas\Stratigility\MiddlewarePipe->handle()
mezzio/mezzio-router#15 /app/vendor/mezzio/mezzio-swoole/src/Event/EventDispatcher.php(39): Mezzio\Swoole\Event\RequestHandlerRequestListener->__invoke()
mezzio/mezzio-router#16 /app/vendor/mezzio/mezzio-swoole/src/SwooleRequestHandlerRunner.php(135): Mezzio\Swoole\Event\EventDispatcher->dispatch()
mezzio/mezzio-router#17 [internal function]: Mezzio\Swoole\SwooleRequestHandlerRunner->onRequest()
mezzio/mezzio-router#18 /app/vendor/mezzio/mezzio-swoole/src/SwooleRequestHandlerRunner.php(79): Swoole\Server->start()
mezzio/mezzio-router#19 /app/vendor/mezzio/mezzio/src/Application.php(68): Mezzio\Swoole\SwooleRequestHandlerRunner->run()
mezzio/mezzio-router#20 /app/bin/server.php(28): Mezzio\Application->run()
mezzio/mezzio-router#21 /app/bin/server.php(29): {closure}()
mezzio/mezzio-router#22 {main} 

Current behavior

Thrown Laminas\Uri\Exception\InvalidUriPartException will be catched by the ErrorHandler middleware and returns a 500 Internal Server Error.

How to reproduce

Provide a request with invalid Host header value.

Expected behavior

The exception should be catched within the Mezzio\Router\Middleware\RouteMiddleware and a 400 Bad Request should be returned.

@weierophinney
Copy link
Contributor

I'm going to note that this is specific to mezzio-laminasrouter; I've tried this with mezzio-fastroute, and it works fine. The issue is with how laminas-http handles invalid hostnames.

One workaround you can do for now is to create a middleware that you pipe after the existing ErrorHandler that looks like the following:

declare(strict_types=1);

namespace App;

use Laminas\Http\Exception\InvalidArgumentException;
use Psr\Http\Message\ResponseFactoryInterface;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Server\MiddlewareInterface;
use Psr\Http\Server\RequestHandlerInterface;

class InvalidUriHostMiddleware implements MiddlewareInterface
{
    public function __construct(private ResponseFactoryInterface $responseFactory) {}

    public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
    {
        try {
            return $handler->handle($request);
        } catch (InvalidArgumentException $e) {
            if (false === strpos($e->getMessage(), 'Invalid URI')) {
                throw $e;
            }
        }

        return $this->responseFactory->createResponse(400);
    }
}

Honestly, I'm unsure if this is something we can correct easily, because it would require router-specific logic in the error handler at this point to manage. We may need to just document the above solution.

@Ocramius Ocramius transferred this issue from mezzio/mezzio-router Jan 4, 2022
@Ocramius
Copy link
Member

Ocramius commented Jan 4, 2022

Moved to the relevant repo.

@Ocramius Ocramius added the Bug Something isn't working label Jan 4, 2022
@marc-mabe
Copy link
Author

@weierophinney I don't think this is a good idea as

  1. Changing behavior based on exception message isn't a good idea in general
  2. This error could happen in a different context (like accessing another API)

What about catching this error in the middleware and simply handle it as no route matched? This would end up as a 404 not found.

@weierophinney
Copy link
Contributor

What about catching this error in the middleware and simply handle it as no route matched? This would end up as a 404 not found.

We could do it here in the LaminasRouter::match() method, by putting a try/catch block around the $laminasRequest = Psr7ServerRequest::toLaminas($request, true); line, and return a route failure; would that work for your purposes?

@marc-mabe
Copy link
Author

What about catching this error in the middleware and simply handle it as no route matched? This would end up as a 404 not found.

We could do it here in the LaminasRouter::match() method, by putting a try/catch block around the $laminasRequest = Psr7ServerRequest::toLaminas($request, true); line, and return a route failure; would that work for your purposes?

This should work

weierophinney added a commit to weierophinney/mezzio-laminasrouter that referenced this issue Jan 6, 2022
…-http

This patch adds a try/catch block within the `LaminasRouter::match()` method around the conversion of the PSR-7 request to a laminas-http request.
It catches laminas-http `InvalidArgumentException`s, and checks for a previous exception matching a laminas-http `InvalidUriPartException`.
When detected, it returns a `RouteResult` indicating a routing failure; otherwise, it rethrows the exception.

The patch is intended to fix scenarios where the Host header is invalid (e.g. `${ip}`), leading to creation of an invalid URI.

Fixes mezzio#12

Signed-off-by: Matthew Weier O'Phinney <[email protected]>
@weierophinney weierophinney added this to the 3.4.0 milestone Jan 6, 2022
@marc-mabe
Copy link
Author

Thank you 👍

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Bug Something isn't working
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants