CSRF tokens are not 'definitely needed' (as in, forms will work without them) but they are an extremely good idea whenever submitting any data from one webpage, to another webpage/script. There is remarkably little way of trusting that any data page 2
receives came from page 1
(read illustration below). Each page in isolations has no idea what page the user was on before, and even things that are intended to hint at this such as $_SERVER['HTTP_REFERER']
can be easily manipulated by browser users.
CSRF tokens are a page-to-page key giving the receiving page a much higher level of trust that the visitor came from the intended sender page(s). Deployed property they also can prevent data repetition which is also a big bonus and cuts down on unscrupulous spam and wasted CPU cycles.
One aspect that CSRF tokens can be used for:
Assume you have a form on a page, the page is called page1.php
and the form is a send contact email
, where the form is filled in and then sent, the page it's sent to (page2.php) can build and then send a contact email to the intended recipient.
From this the next step is someone can read the source code of the page1.php
form. this is trivially easy and tells people what $_POST
values exist and the location of the destination the form is sent to (page2.php
).
A simple user will load your page1.php
, spend ten minutes writing a carefully worded email before pressing the SEND button and submitting the form. Off the form goes to the page2.php
which builds its details into an email sent to receiver@email.com
.
Now, if someone takes the source code from page1.php
they can use a simple PHP script (or any other code) processing to send hundreds or thousands of spam forms to page2.php
, each of them with the correct details to generate and send out an email, this can be used for various nafarious processes, they can send forms from numerous other websites, any other parts of the internet or even from entire botnets if they choose to -- page2.php
would be inundated with many requests a second and the receiver of the emails will have a mailbox jammed full of useless form-generated messages.
Enter CSRF token
A CSRF token is a unique key that is saved in the form, upon generation on page1.php
and would typically (but not exclusively) use (possibly randomly) generated $_SESSION
values so that when the form is submitted, and the $_POST
data is sent to page2.php
this is a fairly reliable check that the form is being submitted from the same website. So instead of having whole botnets submitting data to page2.php
and causing many emails, the data is not being acted upon and instead only pages submitted from the same website are being run in the page2.php
script.
Alternaitvely if the above situation where to occur you can also track where bad submissions are coming from and use other processes / scripts to block / ban various other botnets / servers from submitting data to your server.
The above illustration is a form of insurance and process control so you have a strong reliablility that data that passes through a CSRF on page2.php
:
if ($_SESSION['key'] === $_POST['key']){
unset($_SESSION['key']); ///prevent repetition
...
send email
}
(for example).
This if
statement only runs with form data that's been reliably submitted from a reliable source (page1.php
). Thus preventig other servers piggybacking on your scripts, preventing crass attempts at DOS attacks overloading your page2.php
as well as various other positives from knowing that page1.php
sent the data that is being used on page2.php
.
Another aspect CSRF tokens are used for
See in the code above I unset the $_SESSION
CSRF value? This means that if you press F5 or otherwise refresh the page2.php
visit (typing it into your browser or whatever) it will not resubmit the genuine data twice. This can help prevent people filling in a form once and then constantly resubmitting it like an angry teenager on a forum (POST data is always saved in the page HTTP header and resubmitted when the page is called, so unsetting $_POST
data in PHP is pointless. ).
CSRF is a security mechanism that - when the CSRF token test is passed - means you can reliably judge that data sent to a script on your server came from a valid and intended source.