Add Random String Verification to Prevent CSRF

Cross-Site Request Forgery(CSRF) is difficult to trace, it could cause great harm. The attacker can use CSRF to prank, send spam information, delete data and so on. So how do we prevent CSRF?
To deal with increasing CSRF attacks, Yahoo added a random string called crumb to the form. Facebook has similar solution, if you pay attention to Facebook URLs, you’ll notice there’re post_form_id and fb_dtsg in the URLs.
The common and easy solution is add a random string to any forms related to visitor’s writing operation, then validate this string when processing data. If this random string is associated with current user, then it would be more troublesome for the attacker to forge the requests. Many prevention methods are based on this principle. You can see this random string is very similar to Token.

How to Create String Verification?

Let’s make a simple demo of crumb, here is the code:

    <?php    
    class Crumb {
        CONST SALT = "your-secret-salt";                                                             
        static $ttl = 7200;                                                                                            
        static public function challenge($data) {    
            return hash_hmac(’md5’, $data, self::SALT);    
        }                                                                                                                 
        static public function issueCrumb($uid, $action = -1) {    
            $i = ceil(time() / self::$ttl);    
            return substr(self::challenge($i . $action . $uid), -12, 10);    
        }                                                                                                                 
        static public function verifyCrumb($uid, $crumb, $action = -1) {    
            $i = ceil(time() / self::$ttl);                                                                               
            if(substr(self::challenge($i . $action . $uid), -12, 10) == $crumb ||    
                substr(self::challenge(($i - 1) . $action . $uid), -12, 10) == $crumb)    
                return true;                                                                                        
            return false;    
        }   
    }
?>

$uid refers to user’s identification, $ttl is the valid time span for this crumb.

How to Use String Validation?

Modify the form

Insert a hidden input for crumb string in your form:

   <form method="post" action="demo.php">    
    <input type="hidden" name="crumb" value="<?php echo Crumb::issueCrumb($uid)?>">    
    <input type="text" name="content">    
    <input type="submit">    
    </form>

Validate the form: demo.php

Check the crumb:

<?php    
    if(Crumb::verifyCrumb($uid, $_POST[’crumb’])) {    
        //Pass verification, do something
    } else {    
        //Verification failed
    }
?>

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>