Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
310 views
in Technique[技术] by (71.8m points)

php - New CSRF token per request or NOT?

So I am reading around and was really confused about having a CSRF token, whetever I should generate a new token per each request, or just per hour or something?

$data['token'] = md5(uniqid(rand(), true));
$_SESSION['token'] = $data['token'];

But let's say it's better to generate a token each hour, then I would need two sessions: token, expiration,

And how will I proceed it to the form? Just put echo $_SESSION['token'] on the hidden value form and then compare on submit?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

If you do it per form request - then you basically remove the ability for CSRF attacks to occur & you can solve another common issue: multiple form submission

In simple terms - your application will only accept form input if the user ASKED for the form prior to the submission.

Normal scenario: User A goes to your website, and asks for Form A, is given Form A plus a unique code for Form A. When the user submits Form A, he/she must include the unique code which was only for Form A.

CSRF Attack scenario: User A goes to your website, and asks for Form A. Meanwhile they visit another "bad" site, which attempts a CSRF attack on them, getting them to submit for a fake Form B.

But your website knows that User A never asked for Form B - and therefore even though they have the unique code for Form A, Form B will be rejected, because they dont have a Form B unique Code, only a Form A code. Your user is safe, and you can sleep easy at night.

But if you do it as a generic token, lasting for an hour (like you posted above) - then the attack above might work, in which case you've not achieved much with your CSRF protection. This is because the application does not know that form B was never asked for in the first place. It is a generic token. The WHOLE POINT of CSRF prevention is to make each form token unique to that form

Edit: because you asked for more information: 1 - you dont have to do it per form request, you can do it per hour/session etc. The point is a secret value that is given to the user, and resubmiited on the return. This value is not known by another website, and thus cannot submit a false form.

So you either generate the token per request, or per session:

// Before rendering the page:
$data['my_token'] = md5(uniqid(rand(), true));
$_SESSION['my_token'] = $data['my_token'];

// During page rendering:
<input type="hidden" name="my_token" id="my_token" value="<? php echo $_SESSION['my_token']?>" />

// After they click submit, when checking form:
if ($_POST['my_token'] === $_SESSION['my_token'])
{
        // was ok
}
else
{
          // was bad!!!
}

and because it is "per form" - you wont get double form submissions - because you can wipe the token after the first form submission!


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...