can we hijack CSRF token by ajax request - php

My question is about csrf tokens, the goal of these tokens and can we fake it ..
Problem identity
let's assume that we have bank.com that have this url to make a trasaction to an account
bank.com/ make -transactions?amount=100USD&to=[accountId]
that link will only be accessible by authenticated users (depends on the SessionID in cookies) from a page that has transaction form in bank.com site
The problem comes when a malicious.com put a fake form with hidden fields that submit it’s data to the above url. Causing the SessionID in cookies (related to bank.com) to be sent by this submission and the trasaction will be done
The CSRF solution
This solution depend on generate token (CSRF token) that send with the bank.com page of making transaction (in hidden field ) and save in current user session
And after user submite data from the transaction page, this token (which will be submited with the data) will be checked against the CSRF token value in the user session and if they are equal then the transaction is valid and if not that mean that there is something wrong and the transaction should be rejected
And by this it prevents the malicious.com from making a transactions by submit fake requests .Because it has no way to get this CSRF token and inject it with the request.
My questions
1- what if the malicious.com makes ajax request from the user browser to bank.com (that request will send the bank.com related cookies. am I right ?) and it will extract the CSRF token from the response. and inject that token in it’s fake form. Will this fake the bank.com with this hijacked token?
2- can I generate CSRF token from ajax endpoint in single page application (let say befor take the action. Ask the server for a CSRF token and submit this token with the action ) or not (if I can what I should be aware of ) ?
Thanks for your time with my best regards

what if the malicious.com makes ajax request from the user browser to bank.com
… then the browser's Same Origin Policy will stop the malicious site from reading the content of the page (unless you explicitly allow it using CORS … don't do that).
can I generate CSRF token from ajax endpoint in single page application (let say befor take the action
Yes

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!

CSRF only needed for ajax

I have recently been working with a way to stop CSRF attacks happening by using a token. To my understanding:
1) User logs in, set session cookie to logged in and generate CSRF token and save it to the session
2) User submits form (with token) and it should match the token in session
Hypothetically lets say I have page1.php which has a sql SELECT to get all the users account information and then within the same page I also have an ajax button to page2.php which changes the account information. Obviously I protect page2.php from CSRF (because this is a post request) but how do I protect against page1.php? If this page was to get called from a remote source by ajax or putting an iframe on an attackers website, surely this would print all of the victims account information?
If this is the case how come I can't seem to find anything on protecting all pages from CSRF attacks and I only find resources for protecting against CSRF attacks in ajax?
Suppose you have a page at http://application.com/mypage with some data and a CSRF token generated. Attacker creates http://attacker.com/attack, and when a valid user of application.com visits, makes a request (either via ajax or in an iframe, doesn't matter) to application.com in order to get hold of application data. Standard csrf.
The reason this won't work for the attacker is the same origin policy. When the victim user is on attacker.com, the request to application.com will be cross-domain. If it's an iframe, data will be displayed, but attacker.com will have no access to it, it will only be displayed for the user that could have a look on application.com anyway. If it's an ajax call, the same applies, javascript on attacker.com will have no access to the response, ensured by the browser.
For ajax calls, access to cross-domain responses can be explicitly enabled by the access-control-allow-origin and related response headers (CORS) sent by application.com in the response.
Note that despite being cross-domain, the call will still be made (preflight requests come into play in some cases, but let's not go into that now). It's only the response that will be inaccessible for the attacker, and that is enough to prevent csrf.
(Also as a sidenote, application.com should prevent being displayed in an iframe by for example sending an x-frame-options: sameorigin header to prevent clickjacking and similar attacks, but that was not the question.)
I am not sure I get the point but the token for CSRF should be a nonce, which changes on each call.
Regarding a call coming from some other place, the ajax request should also check that the call comes from a valid user with the correct entitlments as you would do with any "regular" call to the site.
If this is the case how come I can't seem to find anything on
protecting all pages from CSRF attacks and I only find resources for
protecting against CSRF attacks in ajax?
What you ussually do is to set a nonce in a hidden input of the forms you use in "regular" pages.
Hypothetically lets say the page has a sql select on it and does not
request post. Now if this page was to get called from a remote source
by ajax or putting an iframe on their website, surely this would print
all of the victims data?
Make sure that all requests that hand out "confidential" information (either as a webpage or as data for an ajax call (or whatever in the future) do validate that there is a valid session active. If it's not, make sure the server side portion does not hand out anything confidential but instead throw an error and make sure your ajax client understands it and does the right thing for normal users (like telling them they're not logged in and offering them to fix that).
If this is the case how come I can't seem to find anything on
protecting all pages from CSRF attacks and I only find resources for
protecting against CSRF attacks in ajax?
For regular post requests typically the form is output with a hidden input field that holds the CSRF token. That's all.
BUT do make sure the code processing the request validates that the hidden field is present and filled in with the right value.
Also make sure that any request that modifies things is CSRF protected. E.g. that delete button in a non-ajax context should be protected with sending and validation of the CSRF token (hence the button ends up as a form with a hidden field for the CSRF.

Is my CSRF protection method secure?

I've been doing my own CSRF protection using PHP. From what I've read I decided to use a cookie to implement my protection but feel a little confused as to whether my method is secure against CSRF attacks.
So my method follows:
User sends request to login
Server checks if a CSRF token is set, if not create one and store it in their Session and create a Cookie with the token as well
Validate the CSRF token through checking if it is in the POST request, if not then check for the token in $_COOKIE
Send message back if token is invalid...
I decided to use a cookie to store the token as this will work for Ajax requests and I won't have to include it every time I use an Ajax POST.
What I am confused about is couldn't an attacker just make a request; POST or GET and because the cookie is there it just gets sent with the request anyway, thus being a valid request as the token is sent with the browser every time?
The cookie should not contain the CSRF token. Only the client side session storage should contain it. And you should not against a CSRF that is in the cookie.
If you would check a CSRF that is send with the cookie you would bypass the idea behind CSRF.
A simple attack scenario would be a hidden form on a foreign website:
<form method="method" action="http://site-to-gain-access-to.tld/someactionurl">
<!-- some form data -->
</form>
And this hidden form will be executed using javascript without the user's intervention. If the user is logged in on the site site-to-gain-access-to.tld and if there is no CSRF protection active then it would be like if the user itself would have triggered that action, because the session cookies of the user will be send with that request. So the server would assume that it was the user that triggered that request.
If you now would place the CSRF token in your cookie you would have the same problem as with a session.
The CSRF token has to be always sended only as part of the request body or url, and not as cookie.
So the the highlighted parts:
Server checks if a CSRF token is set, if not create one and store it in their Session and create a Cookie with the token as well
Validate the CSRF token through checking if it is in the POST request, if not then check for the token in $_COOKIE
would break the CSRF protection. It does not matter if the CSRF is stored in the cookies as plaintext or with a server side encryption.
As long as "User sends request to login" refers to the initial GET request for the login page, this is correct. The CSRF should be generated and stored on the GET request and validated during every POST.
What I am confused about is couldn't an attacker just make a request; POST or GET and because the cookie is there it just gets sent with the request anyway, thus being a valid request as the token is sent with the browser every time?
Yes. CSRF tokens are not secret. They simply confirm that a POST is made only after making an expected GET request. Meaning someone can only submit a form if they requested the form in the first place. It prevents an bad site from sending a user across to your site with a POST. It does not prevent an attacker from making a GET request, grabbing a token, and making a valid POST.
From OWASP:
With a little help of social engineering (such as sending a link via email or chat), an attacker may trick the users of a web application into executing actions of the attacker's choosing. If the victim is a normal user, a successful CSRF attack can force the user to perform state changing requests.

How to check CSRF token serverside if i am not using session cookies?

In our current project, we implement persistent sessions by using cookies. When the user logs in a session hash is generated and sent via a user cookie. On every page load that is checked with the corresponding session entry in the database and the user is authenticated.
In the past if i had to do csrf token check, i would normally have assined a session variable for the particualar session. And on every subsequent ajax calls i would have matched the csrf token sent as a custom header in the ajax request, with the session variable.
However for the present project i cannot find a proper way to do this. A secure hash can be created and can be added as a custom header or as a hidden input field or even as a parameter in the ajax request. But how do i validate it on the client side ?
For the time being i am doing something like str_rot13(base64_encode(some_secret_key)) and sending it as the csrf token.
Then on the server side i am doing the reverse, obtaining the secret_key and matching it with the secret key that i have configured for my app. This however doesn't seem at all secure to me. I have thought of using openssl_random_pseudo_bytes(32) , openssl_random_pseudo_bytes(16) etc.. But again, thats a hash i would be generating. How would I validate it on the server side?!
What can be some best practices that i can adopt, given the user authentication mechanism that i am following?

security token problem with ajax requests

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.

Categories