Skip to content

Commit 6fd0c63

Browse files
authored
Documented Contao's CSRF protection framework (#284)
1 parent 2a1f9a9 commit 6fd0c63

File tree

1 file changed

+94
-0
lines changed

1 file changed

+94
-0
lines changed
Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
---
2+
title: "Request Tokens (CSRF Protection)"
3+
description: "CSRF protection in Contao"
4+
alias:
5+
- /framework/request-tokens/
6+
---
7+
8+
Cross Site Request Forgery (CSRF) is a very common security vulnerability. In its essence, it allows attackers to
9+
execute unwanted requests on behalf of their victim.
10+
For example, an attacker might let a logged-in user submit a form containing politically incorrect data which is
11+
then stored and assigned to that logged-in user.
12+
You can find more information about how CSRF attacks work and how they can be mitigated on [the respective
13+
website of the Open Web Application Security Project][OWASP_CSRF].
14+
15+
The way Contao mitigates these attacks is by using the [Double Submit Cookie technique][OWASP_Double_Submit_Cookie].
16+
17+
Providing CSRF protection for users that are not authenticated against the app does not make any sense. So if you
18+
visit a regular Contao page with a form placed on it, you will not necessarily see any cookies being set in your
19+
browser. Only if you are authenticated in such a way that the browser will automatically send authentication information
20+
along without any user interaction (logged in via `Cookie` or basic authentication via `Authorization` headers), CSRF
21+
protection is required. So don't get fooled by the cookies not being present all the time, Contao is actually very smart
22+
about them to improve HTTP cache hits.
23+
24+
By default, Contao protects all `POST` requests coming from Contao routes. That means, routes that either do have
25+
the Route attribute `_scope` set to `frontend` or `backend`.
26+
27+
If you explicitly want to disable the CSRF protection on your own route, you can set the route attribute `_token_check`
28+
to `false`.
29+
For example, you might want to listen to some webhook which sends you `POST` data and authorizes itself using the
30+
`Authorization` header. If you need to run in e.g. `frontend` scope, CSRF protection will kick in and you might need
31+
to disable the check for your route.
32+
However, requiring the `_scope` to be set to `frontend` is highly unlikely for a webhook and this example is rather
33+
for illustration purposes.
34+
Remember, Contao is very smart about determining when CSRF protection is required!
35+
36+
{{% notice warning %}}
37+
Setting `_token_check` to `false` will make your custom route vulnerable to CSRF attacks! Only do this if you have
38+
alternative protection in place!
39+
{{% /notice %}}
40+
41+
42+
## Checking The Token Manually
43+
44+
If, for some reason, you need to check the request token yourself, you can do so by combining the token manager
45+
service (`@contao.csrf.token_manager`) and the configured token name (`%contao.csrf_token_name`):
46+
47+
```php
48+
namespace App;
49+
50+
use Symfony\Component\Security\Csrf\CsrfToken;
51+
use Symfony\Component\Security\Csrf\CsrfTokenManagerInterface;
52+
53+
class MyTokenCheckService
54+
{
55+
/**
56+
* @var CsrfTokenManagerInterface
57+
*/
58+
private $csrfTokenManager;
59+
60+
/**
61+
* @var string
62+
*/
63+
private $csrfTokenName;
64+
65+
public function __construct(CsrfTokenManagerInterface $csrfTokenManager, string $csrfTokenName)
66+
{
67+
$this->csrfTokenManager = $csrfTokenManager;
68+
$this->csrfTokenName = $csrfTokenName;
69+
}
70+
71+
public function check(string $tokenValue): bool
72+
{
73+
$token = new CsrfToken($this->csrfTokenName, $tokenValue);
74+
75+
return $this->csrfTokenManager->isTokenValid($token);
76+
}
77+
}
78+
```
79+
80+
81+
## Deprecated Constants And Configuration Settings
82+
83+
For historical reasons, you may still come across the following constants or configuration settings.
84+
They are all deprecated and you must not use them anymore. Register your own route and implement your own
85+
handling as outlined above, if you need to disable the CSRF protection for some reason.
86+
87+
* The constant `BYPASS_TOKEN_CHECK`. It disables CSRF protection completely.
88+
* The localconfig configuration value `disableRefererCheck`. It disables CSRF protection completely.
89+
* The localconfig configuration value `requestTokenWhitelist`. It can contain an exact hostname or regular expression.
90+
It will disable CSRF protection only on hostname match.
91+
92+
93+
[OWASP_CSRF]: https://owasp.org/www-community/attacks/csrf
94+
[OWASP_Double_Submit_Cookie]: https://owasp.org/www-project-cheat-sheets/cheatsheets/Cross-Site_Request_Forgery_Prevention_Cheat_Sheet#double-submit-cookie

0 commit comments

Comments
 (0)