Search code examples
phpformscsrf

How can I pass a token generated on one PHP form to a form that processes it?


I'm trying to secure my forms from CSRF attacks by generating a unique token on each one. I have a hidden field on my form that generates a unique token like so:

public static function generateToken() {
        return $_SESSION['token'] = md5(uniqid(mt_rand(), TRUE));
}

I know that md5 is depreciated and should not be used because it isn't as random as something like:

base64_encode(openssl_random_psuedo_bytes(32));

But I currently don't have ssl installed and I will take care of this. But my main question is, after generation of this token it is stored into the session that the user is currently in like so:

$_SESSION['token'] = $_POST['token'];

It grabs the value of the field that has the generated token in it. Now that I have this token stored into the session, I need to figure out away to send it to the processing file. I have a lot of fields on this form so it will look a bit weird to check every single thing in one if() statement. I guess what I'm trying to say is, how can I check this token on the form that processes the data and if the token isn't the same as the token generated on the form, can I reject that data? Just use die() to kill the processing script?

I'm also wondering if I even need to do this - I've read up on CSRF but I suppose the worst someone could do is change some of the information that is being sent for processing, which is why I'm wanting to pass the tokens to check and reject the data is this happens.

<form name="form1" action="processing.php" method="POST" enctype="multipart/form-data">

This is what I mean by other file. The PHP isn't all in one place, I get everything on the processing script through the $_POST method.


Solution

    1. Generate and save token in server side (sql or others..)
    2. Create cookie with the token (client side)
    3. When the form is submit, retrieve the token from cookie
    4. if the cookie is the same than the saved token, thats ok

    Generate token:

    $formName = "signin"; // name of the form 
    $ip       = get_ip(); // create a function to get the ip of the user
    $salt     = "8077_(-(àyhvboyr(à"; // uniq secret salt
    $token    = md5(sha1($salt.$ip).sha1($salt.$formName));
    ...
    
    if(empty($_COOKIE['token'])){ // if(empty($_SESSION['token'])){ 
    
        setcookie("token",$token, time()+3600*1); // use with cookie // time()+3600*1 = now + 1 hour
        $_SESSION['token'] = $token; // OR use with session
    
    }else{
    
        // when the form is submit regenerate the token and compare with the request token
        if($_COOKIE['token'] == $token){ // OR if($_SESSION['token'] == $token){
           // request from server - ok
           // ...
        }else{
            // bad request
            setcookie("token",0); // destruct cookie
            $_SESSION['token'] = "";  // OR destruct session
            // redirect at the first form
        }
    }
    
    
    <form>
        // if you want use the token directly in your form, add this :
        <input type="hidden" name="token" value="<?php echo $token ?>" />
    </form>