php form: prevent outside posters with tokens - php

I'm making a web game for fun with lots of forms that post data to php pages. What are some methods to preventing people from using their own web forms to post to my site?
My knowledge PHP is not too advanced. So, while I've been researching this topic, unfortunately the answers I've found have been confusing me a little. I found this SO question from earlier that addressed the issue: Secure ajax form POST. I'm a little confused by the first answer and was wondering if somebody could provide an example in PHP. Some specific points I'm struggling with are:
how would you save a token somewhere on your server?
how do you decide what that token should be?
if somebody is on the website, can't they just view the source and
see the token in the hidden input element and use that in their own
third party form?
Thanks for your help!

There are a number of CSRF prevention libraries you can use. One is CSRFGuard at OWASP
You may also wish to read the main CSRF page to understand the issues and the CSRF Prevention Cheat Sheet to understand the principles behind the implementation design.
If you've read up and understood the issues, it should be a simple job to add your own protection, if you wish to construct your own implementation.
Bear in mind that if you have any XSS vulnerabilities, your CSRF protection can be simply bypassed. So be sure to understand XSS Prevention also.

The token is stored in the user's session along with an expiration date/time
The token can be generated automatically, per-user. It needs to be random enough to avoid guessing.
Yes, but you can combat this by using per-user token generation and expiration. If a token is submitted without an existing user session, or if the token has expired in the current session, redirect the user to an appropriate notification of failure.

Related

Complete Form Token Use Example: Secure storage / retrieval / use of form token PHP

I have browsed/read numerous posts on the subject, got a lot of information (my head is spinning), but few solid (this is how its done properly) answers.
I have several forms on my website, each of which I would like to "secure" using form tokens.
My question is, what is the "secure enough" solution for creating, storing, and retrieving these tokens so that I can be sure the form can be trusted and so that it cannot be exploited by malicious users? There has got to be some sort of accepted "best practice" framework for such a task, I just can't seem to find it; only partial, don't do this, recommendations, without examples of how to do it properly.
What type of hashing algorithm / encryption should be used to create the token?
Should the token be stored as part of the session, in a cookie, or in its own database?
Any other useful information regarding the proper way to secure forms with tokens?
I am concerned with the upmost security as I plan to eventually use the framework in a sales site.
TIA
Edit: Is the link in the comment posted by sємsєм the generally accepted "good-enough" practice?

Securing my site

I'm auditing my website with w3af.
It says it found several issues on my site, but I doubt that's really the case.
One of the issues is:
The URL: http://localhost/en/login is vulnerable to cross site request forgery. It allows the attacker to exchange the method from POST to GET when sending data to the server.
I'm pretty sure it isn't vulnerable to a csrf attack since I have used crsf protection in my forms (field with token which gets checked).
So I am wondering what this message is about:
It allows the attacker to exchange the method from POST to GET when sending data to the server.
I don't care if an attacker would be able to switch from POST to GET or do I?
And if I do can you please explain why I do? How can it be exploited?
Coming from a point of view of no experience with w3af, I would assume that it has some pretty basic rules written into it and it checks those rules and reports back on them.
In this case it will probably check whether you have used $_REQUEST instead of $_POST or $_GET and then report an error if it finds it, regardless of the efforts you have made to secure this.
Everyone will code differently so getting software to understand the context of your code would be an amazing achievement and probably be beyond the intelligence of this one. This is not meant as an attack on the software, but to be honest if I came up with some program that could understand the context and intent of someone else's code, I wouldn't be giving it away on sourceforge :p
Does it matter? Maybe depending on how well you have secured the site (see Marc B's (+1) comment above).
-- EDIT --
By using $_REQUEST instead of specifying $_POST or $_GET you have left yourself open to an area of attack that is easily closed. Not only this but $_REQUEST also includes $_COOKIE. This has been covered here rather than me duplicating someone else's answer.

CSRF tokens - how to implement properly?

I've just setup a simple CSRF protection in my application. It creates a unique crumb which are validated against a session value upon submitting a form.
Unfortunately this means now that I can't keep multiple instances (tabs in the browser) of my application open simultaneously as the CSRF crumbs collide with each other.
Should I create an individual token for each actual form or use a mutual, shared crumb for all my forms?
What are common sense here?
You can do either. It depends on the level of security you want.
The OWASP Enterprise Security API (ESAPI) uses the single token per user session method. That is probably a pretty effective method assuming you have no XSS holes and you have reasonably short session timeouts. If you allow sessions to stay alive for days or weeks, then this is not a good approach.
Personally, I do not find it difficult to use a different token for each instance of each form. I store a structure in the user's session with key-value pairs. The key for each item is the ID of the form, the value is another structure that contain the token and an expiry date for that token. Typically I will only allow a token to live for 10-20 minutes, then it expires. For longer forms I may give it a long expiry time.
If you want to be able to support the same form in multiple browser tabs in the same session, then my method becomes a little trickery but could still be easily done by having unique form IDs.
The OWASP Cheat Sheet has the most definitive answers for this sort of thing. It discusses different approaches and balancing of security vs. usability.
In brief they recommend having a single token per (browser) session. In other words in your case the same token is shared among tabs. The cheat sheet also emphasizes that it is very important not to expose your site to cross site scripting vulnerabilities, as this subverts the per session CSRF token strategy.
As I know about CSRF, you can use
1) Random number and save it into session:
Add it to hidden input called hidden, then when you recive info you can check hidden field with the session value
2) Static config variable (like previous but no session)
The hidden field will contain this value (variable from config). When you validate, you will check the hidden posted and the config security key value
3) HTTP Referer
You can use http referrer to know where user come from then check it with the real domain(this method can attack if your website contain xss).
As I know you can use any solution :)

Using a session token or nonce for Cross-site Request Forgery Protection (CSRF)?

I inherited some code that was recently attacked where the attacker sent repeated remote form submissions.
I implemented a prevention using a session auth token that I create for each user (not the session id). While I realize this specific attack is not CSRF, I adapted my solution from these posts (albeit dated).
https://www.owasp.org/index.php/Cross-Site_Request_Forgery_%28CSRF%29
http://tyleregeto.com/a-guide-to-nonce
http://shiflett.org/articles/cross-site-request-forgeries
However, it still feels there is some vulnerability here. While I understand nothing is 100% secure, I have some questions:
Couldn't a potential attacker simply start a valid session then include the session id (via cookie) with each of their requests?
It seems an nonce would be better than session token. What's the best way to generate and track an nonce?
I came across some points about these solutions being only single window. Could someone elaborate on this point?
Do these solutions always require a session? Or can these tokens be created without a session? UPDATE, this particular page is just a single page form (no login). So starting a session just to generate a token seems excessive.
Is there a simpler solution (not CAPTCHA) that I could implement to protect against this particular attack that would not use sessions.
In the end, I am looking for a better understanding so I can implement a more robust solution.
As far as I understand you need to do three things: make all of you changing-data actions avaliable only with POST request, disallow POST requests without valid referrer(it must be from the same domain) and check auth token in each POST request(POST token value must be the same as token in cookie).
First two will make it really hard to do any harmfull CSRF request as they are usually hidden images in emails, on other sites etc., and making cross-domain POST request with valid referer should be impossible/hard to do in modern browsers. The thid will make it completely impossible to do any harmfull action without stealing user's cookies/sniffing his traffic.
Now about your questions:
This question really confuses me: if you are using auth tokens correctly then attacker must know user's token from cookie to send it along with request, so why starting a valid attacker's own session can do any harm?
Nonces will make all your links ugly - I have never seen anyone using them anymore. And I think your site can be Dosed using it as you must save/search all the nounces in database - a lot of request to generate nounces may increase your database size really fast(and searching for them will be slow).
If you allow only one nounce per user_id to prevent (2) Dos attack then if user opens a page, then opens another page and then submits the first page - his request will be denied as a new nounce was generated and the old one is already invalid.
How else you will identify a unique user without a session ID be it a cookie, GET or POST variable?
UPD: As we are not talking abot CSRF anymore: you may implement many obscure defences that will prevent spider bots from submitting your form:
Hidden form fields that should not be filled(bots usually fill most of form fields that they see that have good names, even if they are realy hidden for a user)
Javascript mouse trackers (you can analyse recorded mouse movements to detect bots)
File request logs analysis(when a page is loaded javascript/css/images should be loaded too in most cases, but some(really rare) users have it turned off)
Javascript form changes(when a hidden(or not) field is added to a form with javascript that is required on server-side: bots usually don't execute javascript)
Traffic analysis tools like Snort to detect Bot patterns (strange user-agents, too fast form submitting, etc.).
and more, but in the end of the day some modern bots use total emulation of real user behaviour(using real browser API calls) - so if anyone really want to attack your site, no defence like this will help you. Even CAPTCHA today is not very reliable - besides complex image recognition algorithms you can now buy 1000 CAPTCHA's solved by human for any site for as low as $1(you can find services like this mostly in developing countries). So really, there is no 100% defence against bots - each case is different: sometimes you will have to create complex defence system yourself, sometimes just a little tweak will help.

When its Necessary to Protect Forms with Token (CSRF attacks)?

As much as I understand, web developer should create token and put it in hidden field of form to prevent CSRF attacks. Also, he should save the same token in a session and then, when form is submitted - check that tokens are equal.
I came to question... is it necessary to do this technique for all forms? I mean, imagine form that is created to sign-in. I can't see any harm done to site and/or user if there is no CSRF protection, because user have no privileges (like he would have if he would be signed-in). The same goes for sign-up... Am I right?
P.S. If I'm wrong, please explain me the concept.
The danger that CSRF tries to prevent is when you have the following situation:
The user has signed-in or whatever, and has a certain level of authority
The bad guy exploits that authority without the user's permission
Sometimes this is by tricking the user into making an HTTP request without knowing it, for example in an image's source attribute.
The forms you want to protect are the forms that require this authority.
On the crazy, off-chance that this didn't actually make sense, Chris Shiflett has an awesome article on CSRF (which you may very well have already read :/)
Generally speaking, you want to protect your form anytime its submission will result in a change of content/state; be it adding it, removing it, editing it or sharing it with an external source ("share on xyz !").
An exemple of forms you wouldn't need to protect is a search box, since it doesn't result in any change of content.
If you're unsure, any form which will result in something being saved/deleted (whether it's on your site or not) should be protected.
And if you are really unsure just add the token, doesn't cost anything to be safe.

Categories