0

I have a url with a $_GET parameter that allows deleting of a record in my database, eg. localhost/app/delete.php?id=4843.

The delete.php page only checks to see if the user is signed in and that they own the db record. Obviously, this creates the perfect opening for a CSRF attack. Should I generate the nonce when the page loads, or do I somehow do it only when the user clicks the URL? How would I?

Here's my code so far:

function nonce_create() {
   $_SESSION["nonce"] = random_bytes(12);
   $_SESSION["nonce_time"] = time();
}

function nonce_verify() {
   $time = time() - 90; /* give browser 90 seconds to load */
   if (isset($_SESSON["nonce"]) && strlen($_SESSION["nonce"]) == 7 && $_SESSION["nonce_time"] > $time) {
      $_SESSION["nonce"] = null;
   }
   else {
      header("location: index.php");
   }
}

The nonce_create() function above would be called when loading the page where there are links to the delete.php page, and the nonce_verify() function would be called when the nonce needs to be verified and removed on delete.php.

John S
  • 1
  • 2
  • 3
    Side note - its best to not use GET to delete or modify anything. Its good practice to have a GET requests to only return data. – ISMSDEV Oct 31 '17 at 16:22
  • 1
    I recommend the OWASP CSRF Protection cheat sheet https://www.owasp.org/index.php/Cross-Site_Request_Forgery_(CSRF)_Prevention_Cheat_Sheet – iainpb Oct 31 '17 at 16:34
  • 1
    Could you try to explain what you think your code would do, and when the functions should be called? I'm not sure I understand it. – Anders Oct 31 '17 at 16:36

1 Answers1

1

I'm not sure I understand how your code could work. You set a nonce in the session, and then you check that it is still there? That will always be the case!

Just using the session does not help, since the session is kept together with the help of a cookie. And cookies are sent on all requests, so the sesion cookie would be included in the CSRF reqeusts. You can not use sessions alone to tell CSRF attacks and legitimate reqeustst apart.

Proper CSRF protection requires that the client put the nonce (or the token as it is commonly called) somewhere else, such as in a HTTP header, where the victims browser would not automatically include it. And then you can check that that value corresponds to the value you have stored in the session.

As for when to generate the token, I would say that one token per session is enough. Every time you get a request from a session that does not have a token, generate a new one for them and keep it for the duration of the session.

There are a lot of details to how to implement this, and it is not possible to include everything in here. Instead, I will recommend you to do this:

Anders
  • 64,406
  • 24
  • 178
  • 215