Unique form token disables multitasking for the user

喜夏-厌秋 提交于 2019-12-09 06:56:48

问题


If I want to protect my site and users from Cross Site Forgery (CSRF) attacks, I can generate a unique token $token = md5( time() * rand ); on every page that has a form. The token is is submitted in a hidden input field echo '<input type="hidden" name="token" value="'.$token.'">'; and at the same time stored in a session variable $_SESSION['token'] = $token;.

I will check if on any submitted form if($_POST['token'] == $_SESSION['token']) and proceed accordingly.

However some users may multitask. Which is something that I am actually doing right now, while I am posting this.

While composing my post I open different windows / tabs to possibly research information or look at some other questions on stack overflow. Stack overflow lets me submit the form with no problems.

But if I were to do that on my site doing this - meaning browse other pages while still composing a post/form - my $token would be regenerated each time I pull up a different page from my website. Making the hidden input token on the form I am working on and eventually want to submit incorrect, because it wont match the $_SESSION['token'] variable anymore, which has been regenerated when I visited a different page...

Any good ideas how to prevent this issue, or any better solutions to stop CSRF in the first place?

I want to allow my users to multi task AND want to be protected against CSRF...


回答1:


I've had the same problem with what you state because of single CSRF and it gets replaced unless they submit the latest page, but if you use a array w/session it should solve your problem(s). Also you might want to include a captcha, I'd recommend Google's Recaptcha.

session_start();
function createToken(){
    $token = sha1(uniqid(mt_rand(), true));
    $_SESSION['Tokens']['Token'][] = $token;
    $_SESSION['Tokens']['Time'][] = time() + (10 * 60); #10 min limit
    #you can omit/change this if you want to not limit or extend time limit
    return $token;
}

function checkToken($token){
    clearTokens();
    foreach($_SESSION['Tokens']['Token'] as $key => $value){
        if($value === $token){
            return true;
        }
    }
    return false;
}

function clearTokens(){
    foreach($_SESSION['Tokens']['Time'] as $key => $value){
        if($value <= time()){
            unset($_SESSION['Tokens']['Token'][$key], $_SESSION['Tokens']['Time'][$key]);
            #remove last parameter if you aren't using token time limit
        }
    }
}

your HTML:

<input type="hidden" name="token" value="<?php createToken(); ?>">

PHP Token Checker

if(isset($_POST['token']) && checkToken($_POST['token'])){
    #valid token
}else{
    #create error message saying that they tried to repost data or session token expired
}



回答2:


The browser should keep the correct session id even between tabs and windows the session id should be the same. (dangerous assumption should be tested cross browser to be sure)

generate more tokens that should be valid based on session id.

so you could check something like this.

$tokenCorrect = false;

foreach($_SESSION['tokens'] as $token) {
  if ($token !== $_POST['token'])
     continue;
  $tokenCorrect = true;
}

if ($tokenCorrect == false) {
   die(); // 
   // Maybe log to database ?? but watch if possible Denial of Service because somebody can write your disk/ shared diskspace full with only making fast requests with a invalid CSRF token
}


来源:https://stackoverflow.com/questions/18238614/unique-form-token-disables-multitasking-for-the-user

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!