security token problem with ajax requests - php

when building apps I use a token to prevent attacks on the forms
each time a form is rendered it gets a new ONE TIME security token that i include in the form as a hidden field. this token is also stored in the session.
when the form is sent, the token is verified against the token in the session to make sure the form is legit. This works great for standard pages.
PROBLEM
when using Ajax to send forms, there may be multiple on a page, once you send one of these forms, the token is then invalid for the others as its a one time token.
does anyone have advise for this? or is it secure enough to generate one token per session and just use that instead of invalidating the token each time a form is sent?

If you want to follow your current approach, you can generate a security token each time you do a an AJAX request, return it in the AJAX response, and inject it into the hidden when you get it.
However, I'd go rethinking your current approach for security tokens. Here you have some tips about that in the OSWAP wiki.

Related

CSRF session in HTML form

In CSRF form protection we use session right. Let consider if I have login PHP at the same login page. And I want to make secure my login form with CSRF.
At one page how we add two sessions. ?
One session we will start when user login and second we use at login CSRF.
How it possible. Please help to send sample demo.
Thanks in advance.
Although the question is vague I'll take a stab at the answer. To protect yourself from CSRF here is what you need to do in principle in it's simplest form.
When an initial request is made on your login page where you render the login form, generate a unique token/hash server side and store it in your session or perhaps another datastore.
When you render the login page store this token client side either in a cookie or as a hidden form field.
When the user fills up the form and submits the request, First ensure the unique token is valid then authenticate the user. If the unique token doesn't match then they either tampered with the token or are trying to make post request in an automated fashion.
CSRF is most applicable for users that have logged in because if the token were to fall into wrong hands worsts things can happen. So in that case once the person has logged in for every active user session you will generate a unique token for every request to ensure that it's actually the authenticate users that making the request.
Hope this helps!

How to prevent Cross-site request forgery (CSRF) effectively in PHP

I am trying to prevent CSRF in php in the following way:
A $_SESSION['token'] is generated at the start of each page. I already know that using $_COOKIES is completely wrong since they are send automatically for each request.
In each <form>, the following input: <input type="hidden" name="t" value="<?php echo '$_SESSION['token']; ?>"> is appended.
The $_SESSION['token']; is validated with the $_POST['t']
Now I have several small questions:
Is this a good way to prevent CSRF? If not please explain.
When another page is opened as well that sets the same $_SESSION variable, the previous (still open) page becomes invalid, how to prevent this?
For forms this method is clear, but how to handle normal links? Is it necessary to append the token to each link as well?
Thank you very much in advance.
Is this a good way to prevent CSRF?
Yes. What this does is to force the client to do a GET on the form before it can do a POST to your form handler. This prevents CSRF in modern browsers since browsers will prevent client-side Javascript to do an XHR GET request to a foreign domain, so a 3rd party cannot imitate your form on their site and successfully get a valid token for the submission.
When another page is opened as well that sets the same $_SESSION variable, the previous (still open) page becomes invalid, how to prevent this?
Allow several tokens to be valid at a time, keeping an array of valid tokens in the session. Alternatively, store no tokens at all and use a token signing scheme instead. I've dabbled in and explained that here. Alternative 2: just use a single token for the whole session, without invalidating tokens. (tip o' the hat to #SilverlightFox in the comments)
For forms this method is clear, but how to handle normal links? Is it necessary to append the token to each link as well?
No. You only need to protect POST requests since presumably only POST requests can alter sensitive data (wink wink nudge nudge, you're sticking to REST conventions, right?!) and XHR GET requests are already blocked browser-side.
CSRF attack occurs when a hacker tries to send a fake request from an authenticated user. normally this attack occurs
in online shops or banks.
Prevent csrf attack in php we can:
1 = Create a check login function:
If the login session is set that is true Ok, if not false and return to login page.
2 = create a random makeToken hash function with: base64_encode(md5(microtime())) and save it into session and create a input hidden type with token name and the value with name Token's function.
3 = Create a checkTocken function and check it, if it is equall to makeToken function, and after that use unset function to unset the session, and create a new one.

CSRF token collisions with multiple tabs

I built CSRF protection in my application, by simply generating a random token on every page load, putting it into session, and then binding the token to the <body> tag attribute like:
<body data-csrf-token="csrf_GeJf53caJD6Q5WzwAzfy">
Then on every form action or ajax request, I simply grab the token from the body tag and send it along.
This works great, except for a huge issue. Users are opening multiple tabs of the application, and I am seeing token collisions. For example, a user loads the first page and it generates a token, then they switch tabs, load another page, which generates a new token. Finally they switch back to the first page and submit a format action. This results in an invalid CSRF token error.
What is the best way to re-architect this to prevent collisions with multiple tabs, while keeping it as secure as possible.
Is simply generating a single token upon login the correct solution, instead of generating a new token on every page load?
Assuming that your app is secured with SSL, then there is really no value created by generating new tokens on every page load. It doesn't stop an attacker who has exploited an XSS vulnerability – they'd have access to the freshly generated token anyway.
Remember what a CSRF token defends against: a malicious third-party page blindly trying to post data to your app in hopes that the user is logged in. In this kind of attack, the attacker would never have access to the CSRF token, so changing it frequently does no good.
Do not waste time and resources keeping track of multiple tokens per session. Just generate one at the start and be done.
You could use a single token upon login. As #Josh3736 points out, this works just fine.
If you really want to have one token per page, you could store an array of valid tokens in $_SESSION. You would then expire individual tokens as they are used. You could also optionally expire them after some timeout period, but that is only meaningful if the timeout is shorter than your session timeouts. But, again, what are you really accomplishing with this? A single token is perfectly fine for CSRF purposes.
I've run into this exact problem, on page load I was generating a CSRF token like this:
$_SESSION["token"] = bin2hex(random_bytes(32));
Multiple tabs was causing CSRF mismatches, so I changed to this:
if (!isset($_SESSION['token'])) {
$_SESSION['token'] = bin2hex(random_bytes(32));
}
Server side I do this (watered down version):
$csrf = preg_replace("/[^a-zA-Z0-9]+/", "", $_POST["token"]);
if ($csrf !== $_SESSION["token"]) {
// Give an error
die ("No valid CSRF token provided");
}
This may protect against XSS attacks, but it wouldn't stop someone going to the page, getting the PHP session ID (from headers) and the CSRF token and using a tool like Postman or WGET to put together hack API posts, etc.
That may be why this question exists... understanding the scope of what the CSRF token is for protecting against.

CSRF Token Multiple tab issue

I am implementing CSRF token in my website on every post method.
But when i am accessing my webpages in different tabs then token gets change on both pages and token mismatches.
My token is stored in DOM and i am matching token using SESSION.
How to solve this.?
i change the token on every successful request
Yeah this is why we don't invalidate the token on every successful request. That doesn't just break multi-tab browsing, it also means you can't do stuff like hit the back button then submit.
“Invalidate token on every request” is the kind of bogus security recommendation you get from pentest reports where the tester hasn't found much that's really vulnerable. It's a trade-off as always whether you do, but the usability downside almost always outweighs the minimal security benefit.
You only really need to invalidate the CSRF token (along with the session token) on a privilege level change, most notably on login. This mitigates session fixation attacks, by preventing an attacker who knows the session and CSRF tokens prior to login from exploiting those tokens after you've logged in.
You can achieve this easily:
In the server side, store the CSRF tokens in session like this:
$_SESSION['csrf_tokens']['form1'] = //code to generate csrf token
While validating the token on form submit, you can check,
$_SESSION['csrf_tokens']['form1'] === $_POST['csrf_token']
Please post an example code, unless you are using ajax (which I wouldn't recommend for CSRF tokens the code shouldn't change in both tabs if you open a new tab). Also, I disagree with bobince, you are doing the right thing to implement this measure as once you have the logic in place you can easily and effortlessly use it in all your forms. The best way to implement this is to just have each token expire after a certain amount of time.
bobince: CSRF tokes are used to prevent CSRF attacks not session fixation attacks, both are different the former prevents scripts from executing actions on behalf of the user whereas the latter is an attack in which a malicious user impersonates a normal user by guessing or stealing their session id.
Generate two values – one random key (f.e. via uniqid), and a random token.
You generate both every time a form is rendered – and put them both into hidden fields. And you save the token into the session using the random key. Then when the form data is received, you check if the token send is in the session under the key send. (And if so, you delete the entry with this key after processing the form of course.)
Anything else (f.e. expiration time of tokens, binding of tokens to a certain form type out of several) you implement the same as you would before.
is unnecessarily and unsafe like this why you dont create a token based on session with openssl_random_pseudo_bytes() ,which will produce a safe token, and check if is correct or not or you can use also to expire after 2-5 min.also you can check on owasp about tokens on dom,can be easy spoffed !!!

For securing forms, when do I issue the token?

So, I have a form, to make it a little more secure and potentially help prevent CSRF attacks I want to add a random token value in a hidden field that value is also stored server side in my session data.
When should I issue a new token? Per form? Per page load where there is any form? Per session? I can render it invalid as soon as a form is successfully submitted but I'm wondering when to generate one.
I ask as if I issue it per form or per page do I not risk the chance of a duplicate token value overwriting the existing (valid) token if a user opens a separate window but submitting the first form (with the now overwritten value)?
The simplest way to prevent concurrency issues is to generate it only once per login. The chance of an attacker "guessing" your CSRF is about the same chance (or lower) as them stealing your PHPSESSID. You could also regenerate it whenever the user's access level changes, such as after they change their password or something.
If you want to be really thorough, you can generate and store an array of tokens, one for each form on the website. But if they can steal a CSRF token, they might as well have just stolen a session ID and done some real damage.
If you use one Token per session,
then you need a technique to check
duplicate submitted forms (when user
refreshes a page or click back
button).
If use it per form then if user opens
multiple pages then only the last
form will work.
I would prefer using array of
generated tokens per session, and
when a token is submitted it should be
removed. I read that this approach might be a
concern if you have high volume
traffic website.
I am not sure if you read this article before, but I think it is great resource about CSRF security:
http://shiflett.org/articles/cross-site-request-forgeries

Categories