0

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'); 
} 
?>
Rus84
  • 33
  • 2
  • 11
  • 2
    You're using `$_GET['token']` but your form uses the `POST` method so you should use `$_POST['token']` instead, i.e. `if ($_POST['token'] !== $_SESSION['token'])` – mrun Apr 30 '15 at 11:34
  • @mrun Thanks for that suggestion, i tried that but it didn't work. I have therefore altered my post. – Rus84 Apr 30 '15 at 11:46
  • Why two `session_start();` lines in your second (validating) file? – Mark Baker Apr 30 '15 at 11:54
  • @MarkBaker They are on two different php files, the top one is on login.php and the bottom one is my destination file. – Rus84 Apr 30 '15 at 12:06
  • 1
    @Rus84 I just tested your code and it's working for me. I don't see a submit button in your form. Are you sure you're submitting it? Try to `print $_POST['token']` in `login.php`. – mrun Apr 30 '15 at 12:12
  • @mrun maybe that's were I'm getting slightly confused. I have a login page where a user will enter their username and password. They will then be sent to their own unique homepage (depending on their userID). On the code that i took from else where i removed the submit tab as didn't think i needed it. I wanted the token to be issued upon clicking the login button. Are you saying that the login button should be my submit button? Changing it to post didn't work, was that the only change and it worked for you? feel free to edit my code at any time so i can see what you did. – Rus84 Apr 30 '15 at 12:22
  • @Rus84 OK so how exactly are you sending the user to their 'unique homepage'? Could you provide some more code please? – mrun Apr 30 '15 at 12:27
  • @Rus84 I put the first code in a file called `post.php` and the second one in `checklogin.php` and it doesn't `die()` after I submit the form. So unless you're doing some kind of redirection in the `checklogin.php` that should be working. – mrun Apr 30 '15 at 12:51
  • @mrun your comments above have helped lots, as I realised my mistake with the submit button. I have included more of the code above, but there is another slight issue. I will explain it in more detail below (person below's comment as links to their point). Thanks for your advise, much appreciated. – Rus84 Apr 30 '15 at 12:51
  • @Rus84 I'm glad you find my comments helpful! :-) Good luck with resolving the other issues! – mrun Apr 30 '15 at 12:54
  • @mrun i am doing redirection in the checklogin. The check login matches the username and password to what is stored in the MAMP database. Then, according to their userID, they are sent to their individual page (this php is stored in the database). I am now assuming that i need to add if ($_POST['token'] !== $_SESSION['token']) { die('expired'); } to checklogin and then to the final document? – Rus84 Apr 30 '15 at 12:54
  • @Rus84 I think it's time to summarize our discussion in an answer so it would be easier for others to find all the information they need in one place – mrun Apr 30 '15 at 13:01
  • @mrun being new to this i apologise for the stupid question but do i do that? by editing the question? – Rus84 Apr 30 '15 at 13:14
  • @Rus84 Sorry, I meant I should write an answer and I just did so. Hope you find it helpful! :-) – mrun Apr 30 '15 at 13:17

2 Answers2

1

The form action is login.php so when a user logs in the POST data is submitted to the login.php page. Your question does not explain how the user then gets directed to their landing page.

One option would be to try the following.

Replace:

<form action="login.php" method="post">

With:

<form action="landingpage.php" method="post">

That way on your landing page you will be able to get the value of

$_POST['token']
someuser
  • 2,279
  • 4
  • 28
  • 39
  • yes you are right. The difficulties are arising as I'm using a redirect on the checklogin. So once they login they go to the checklogin.php, their username and password is compared against what is stored in the database. They are then sent to their own unique page depending on their userID. I am therefore assuming that i need to check that the tokens match up on that page as well as the final php file? – Rus84 Apr 30 '15 at 12:58
  • If I understand correctly you would just need to make sure the tokens match on logincheck.php only. – someuser Apr 30 '15 at 13:04
  • I want to check that the tokens match firstly on checklogin.php and then to their redirected location file1.php. – Rus84 Apr 30 '15 at 13:16
  • Why check the token again? It is really only necessary to check the token on form submit I think. Look at this for more info on how CSRF tokens work: http://stackoverflow.com/questions/5207160/what-is-a-csrf-token-what-is-its-importance-and-how-does-it-work – someuser Apr 30 '15 at 13:19
1

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!

mrun
  • 744
  • 6
  • 19
  • 24
  • yes that summary is correct. The note section is exactly right and that is one of my main concerns regarding security. I am new to php, and learning on the job through trial and error (so to speak). The username, password, page_ID, is all saved in a MYSQL database. will the Id sessions be stored in the checklogin.php? Then on the top of file1.php file2.php etc you will check to make sure that the right user has accessed the file? Thanks – Rus84 Apr 30 '15 at 13:26
  • Yes, exactly. You would save the user id in `$_SESSION` inside checklogin.php and then check in each file whether the user is allowed to access the file. Btw there are a lot more better ways of doing this but since that's the way you have chosen to build your app than that's one of the ways to go. Imagine for a second how many checks you will have to write... in every single file. And then if you decide to add another criteria whether or not the user can access the file? Right! You'll have to change all the files! So you should probably think of a way to improve this part of your app :-) – mrun Apr 30 '15 at 13:33
  • I was wondering if you could help me with the point number two that you recommended above, setting a flag. How would you set something up in the final php file to show that they are able to view the page? Any bits of code that you can suggest is much appreciated. Thanks. – Rus84 May 05 '15 at 16:06
  • Sorry but I was away a couple of days, I'll try to suggest some help later today or tomorrow – mrun May 08 '15 at 06:18