CSRF session in HTML form - php

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!

Related

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.

Using stolen cookie in cURL to bypass CSRF

I have to process a web page. This web page is based on YII framework, and the login page is protected by CSRF tokens. When I pass the login credentials by POST method. I get the error 400 and The CSRF token could not be verified message.
I don't know how to by pass this protection. I don't understand the mechanism. When I login by the Chrome browser, I see what the POST message look like. It has 4 parameters: CSRF key, login, password, an one empty variable. How the browser gets the proper CSRF key to be sanded back?
I have a login and password for this web page, and I can login as normal user. Only the login page is protected against CSRF. Can I use the cookie (how to do that) created by browser on normal login, give this cookie to cURL and start processing URLs behind login page?
MrMgr Answer in his comments. I've put it here to help other people easily identify the answer.
The CSRF key is generated for session and it is inside LOGIN page as plain text. I can copy it from the source code, of the login page, and provide to cURL script to be past as POST variable. The CSRF Key doesn't change after every page refresh, a KEY is valid until logout. On logout the CSRF key is sanded to server for termination.
Source
CSRF tokens are in place to make this precise action difficult. You need a better way to spoof being a browser with PHP. To do that, store all cookies in what is generally called a "cookie jar." PHP's implementation of curl has that capability. All curl requests routed to this site should use this cookie jar from now on.
Next you need to parse the login page to grab all fields that are submitted. This includes the username, password, CSRF, and other hidden fields. Make sure you have values for each one. If it's not supposed to be entered by you (e.g. hidden inputs), scrape the login page's HTML and put those fields into variables you can pass along in the login POST. Also be sure to send the url of the login page you scraped as the referrer in the login POST.
Parsing html can be tedious, but libraries like SimpleHTMLDOM should make it simple if you're familiar with CSS selectors.

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?

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

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