A PHP PSR-15 compliant middleware that checks for CSRF attacks.
This package contains a PHP PSR-15 compliant middleware that checks for CSRF attacks.
Note that OWASP recommends also using a CSRF token. This requires some changes in your application and this middleware does not provide any help regarding CSRF token generation. Other packages (like Slim-CSRF) can help you with CSRF token validation.
CsrfHeaderCheckMiddleware will look at all POST/PUT/DELETE requests (actually all requests that are not GET/HEAD/OPTIONS).
It will verify that the "Origin" of the request is your own website.
It does so by comparing the "Origin" (or the "Referrer" header as a fallback) to your website's domain name. If the headers do not match (or if the headers are not found), it will trigger an exception.
The query is therefore executed by Alice's computer. We can expect Alice's browser to behave as a "normal" browsers.
When fighting CSRF attacks, the most common solution used it to generate a token in each form, store this token in session, and check that the user sends back the token. If you are looking for a CSRF token based middleware using PSR-7/PSR-15, have a look at Ocramius/PSR7Csrf
Checking for HTTP headers can be done in the middleware alone. With token-based middlewares, you have to modify your application to generate a token and send the token with any form. In contrast, checking headers requires no work besides adding the middleware. So it's really fast to deploy.
- This middleware completely bypasses GET requests. If your application modifies state on GET requests, you are screwed. Of course, modification of state should only happen in POST requests (but please check twice that your routes changing state do ONLY works with POST/DELETE/PUT requests).
- This middleware expects "Origin" or "Referer" headers to be filled. This will often be true unless you are in a corporate environment with proxies that are fiddling with your request. For instance, some proxies are known to strip headers in order to make the request anonymous.
- Will block CORS requests. You cannot use this middleware if you are expecting requests to come from another origin than your website.
- If your website is accessed from a third party application (like a phone app), you cannot use this middleware as the Origin and Referer will be empty.
If you are in one of those situations, use a token-based middleware instead.
composer require thecodingmachine/csrf-header-check-middleware
The simplest usage is based on defaults. It assumes that you have a configured PSR-7 compatible application that supports piping middlewares.
application, the setup would look like the following:
$app = \Zend\Expressive\AppFactory::create(); $app->pipe(\TheCodingMachine\Middlewares\CsrfHeaderCheckMiddlewareFactory::createDefault();
This middleware will do its best to "guess" the domain name of your website. To do so, it will check the "Host" header of the HTTP request.
You need to know this:
- Normal browsers always send the "Host" header (at least in HTTP 1.1).
- The "Host" header can be modified by proxies
- Proxies will generally put the previous "Host" header in the "X-Forwarded-Host" header
Therefore, if you run your application behind a proxy, or if you deal for some reason with HTTP/1.0, you will have to manually specify the domain name of your application.
// The first argument of the factory is a list of domain name for your application. $app->pipe(\TheCodingMachine\Middlewares\CsrfHeaderCheckMiddlewareFactory::createDefault([ 'alice.com', 'www.alice.com' ]);
You can disable CSRF checks on a per-route basis:
// The second argument of the factory is a list of regular expressions that will be matched on the path. // Here, we disable CSRF checks on /api/* $app->pipe(\TheCodingMachine\Middlewares\CsrfHeaderCheckMiddlewareFactory::createDefault(, [ '#^/api/#' ]);
This can be useful for APIs that are only used when communicating from server to server. Please note that if you decide to disable CSRF for some routes, you need to have some other forms of protection for this route.
Alternatively, any request passed to the middleware that has the 'TheCodingMachine\BypassCsrf' attribute set will be ignored:
// Put this in a middleware placed before the `CsrfHeaderCheckMiddleware` to disable it. $request = $request->withAttribute('TheCodingMachine\\BypassCsrf', true);