Search code examples
phpcsrf

tokens do not match (CSRF)


I have entered the following code to prevent CSRF but issuing and checking tokens. The top section goes on the login.php, the second part goes on the landing page. The issuing of the token works, and when I print $_SESSION['token']on the landing page they match up. However, when i substitute the other code in, its says that they don't match and shows 'expired'.

<?php
session_start();
$_SESSION['token'] = $token;
$_SESSION['token'] = uniqid(md5(microtime()), true); 
print $_SESSION['token'];
?>

<html>
<head>
    <title>My first PHP website</title>
</head>
<body>
    <h2>Please login here to see your tour</h2>
    <form action= "checklogin.php" method="post">
        Enter Username: <input type="text" name="username" required="required"/> <br/>
        Enter Password: <input type="password" name="password" required="required" /> <br/>
        <input type="hidden" name="token" value="<?php echo $_SESSION['token'] ?>" />
    <input type="submit" value= "login" />

    </form>
</body>

<?php
session_start();

print $_SESSION['token'];
session_start(); 
if ($_POST['token'] !== $_SESSION['token']) { 
die('expired'); 
} 
?>

Solution

  • Following our discussion in the comments of your question I'm posting this answer so the information is summarized.

    Your code is basically correct but the issue you're having is because after the redirect to the user's unique landing page you no longer can access the data in $_POST you originally have in your checklogin.php, i.e. after submitting the login form.

    So in your checklogin.php script you have among others these options:

    1. Include the token in the URL you're redirecting to and then check the $_SESSION['token'] against $_GET['token'].

    2. Set a flag in the $_SESSION indicating that the use has been allowed access to the system. Something like $_SESSION['loggedIn'] = true; (that's what I would recommend)

    NOTE: Here you are facing another issue: you have to think about restricting access of each user to only their own page. Imagine that if a user somehow knows the URL of another user's home page they could easily edit the URL and reach it. My recommendation is to save the user's id in the $_SESSION and then at the top of each user's home page to check whether the currently logged in user is allowed to open the said page.

    I hope that makes it more clear!