Confirming Important Actions Using a One-Time Token
If a user tries to do something that has some importance (such as transferring funds, changing password, or buying goods), make them confirm their intentions before processing the transaction.
In the preceding example, the Insecure Bank Co. shouldn't have transferred the money to Bob's account so easily. Julie should have been forced to fill out a specific form for the transaction to take place.
In this form, you use a one-time token. This is essentially a password that is generated for a specific transaction, which is then required to complete the transaction. It doesn't require the user to enter anything extra; it simply means that a transaction cannot be completed without confirmation.
We'll use the bank example again to demonstrate this. This is how a basic version of the transfer.php script might look with the one-time token added to it. Without the correct token being submitted with the form, the transaction cannot complete, thereby foiling the previous CSRF attack.
// Validate the submitted amount and account, and complete the transaction.
echo 'Transaction completed';
exit;
form method="post" action="transfer.php">
<input type="hidden" name="token" value="<?php echo $_SESSION['token'] ?>" /> <p>
Amount: <input type="text" name="amount" /><br /> Account: <input type="text" name="account" /><br /> <input type="submit" value="Transfer money" />
You first initiate the PHP session. We have simplified this call for now, but you should keep in mind the previous strategies for protecting your sessions.
Next, you check whether a token exists, and create a new one if there isn't already one. You use the uniqid() function to create this unique token. In fact, the code used to generate this token is taken directly from the uniqid() PHP manual page, at www.php.net/ uniqid.
To simplify the example, we have created a form that submits back to itself—so next, you check your stored token against the one submitted. Initially when you run this form, no token is submitted, so obviously the transaction isn't completed.
Finally, you output the form with the generated token. This must be included in the form to complete the transaction.
Post a comment