Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to prevent Cross-site request forgery (CSRF) effectively in PHP

I am trying to prevent CSRF in php in the following way:

  1. A $_SESSION['token'] is generated at the start of each page. I already know that using $_COOKIES is completely wrong since they are send automatically for each request.

  2. In each <form>, the following input: <input type="hidden" name="t" value="<?php echo '$_SESSION['token']; ?>"> is appended.

  3. The $_SESSION['token']; is validated with the $_POST['t']

Now I have several small questions:

  • Is this a good way to prevent CSRF? If not please explain.
  • When another page is opened as well that sets the same $_SESSION variable, the previous (still open) page becomes invalid, how to prevent this?
  • For forms this method is clear, but how to handle normal links? Is it necessary to append the token to each link as well?

Thank you very much in advance.

like image 629
Bas van Stein Avatar asked Nov 18 '15 09:11

Bas van Stein


People also ask

How can cross-site request forgery CSRF be prevented?

The most effective method of protecting against CSRF is by using anti-CSRF tokens. The developer should add such tokens to all forms that allow users to perform any state-changing operations. When an operation is submitted, the web application should then check for the presence of the correct token.

Which is the best defense against Cross-Site Request Forgery CSRF attacks?

The most robust way to defend against CSRF attacks is to include a CSRF token within relevant requests. The token should be: Unpredictable with high entropy, as for session tokens in general. Tied to the user's session.

Which cookie setting is used to help prevent CSRF attacks?

Some web sites defend against CSRF attacks using SameSite cookies. The SameSite attribute can be used to control whether and how cookies are submitted in cross-site requests.

How does CSRF work in PHP?

CSRF stands for cross-site request forgery. It's a kind of attack in which a hacker forces you to execute an action against a website where you're currently logged in. For example, you visit the malicious-site.com that has a hidden form. And that form submits on page load to yourbank.com/transfer-fund form.


1 Answers

Is this a good way to prevent CSRF?

Yes. What this does is to force the client to do a GET on the form before it can do a POST to your form handler. This prevents CSRF in modern browsers since browsers will prevent client-side Javascript to do an XHR GET request to a foreign domain, so a 3rd party cannot imitate your form on their site and successfully get a valid token for the submission.

When another page is opened as well that sets the same $_SESSION variable, the previous (still open) page becomes invalid, how to prevent this?

Allow several tokens to be valid at a time, keeping an array of valid tokens in the session. Alternatively, store no tokens at all and use a token signing scheme instead. I've dabbled in and explained that here. Alternative 2: just use a single token for the whole session, without invalidating tokens. (tip o' the hat to @SilverlightFox in the comments)

For forms this method is clear, but how to handle normal links? Is it necessary to append the token to each link as well?

No. You only need to protect POST requests since presumably only POST requests can alter sensitive data (wink wink nudge nudge, you're sticking to REST conventions, right?!) and XHR GET requests are already blocked browser-side.

like image 170
deceze Avatar answered Oct 19 '22 17:10

deceze