I think the answer to my question is no, but I just wanted some clarification. I have a webpage which requires no login whatsoever. Users are essentially anonymous. The form requires them to fill in personal information, and then upload a couple of sensitive documents.
Considering the sensitive information they will upload, would CSRF protection make sense? Keep in mind that there is no login required, so I am not too sure if it would be of any use?
Any clarification appreciated.
Thanks
CSRF basically prevents an attacker do something in another user's name (through that user's machine and internet connection). If you are worried about that (e.g. you record IP addresses and you don't want an attacker to send a request with someone else's IP, or record someone else's IP against their will), you should use CSRF protection. If you are not worried about it, you should use CSRF protection anyway, it's a good practice :) but you don't need to.
Also, CSRF cannot be used to upload files (barring browser bugs or very permissive CORS settings).
Related
Using PHP, is there a way to check for certain how a web server resource is requested while minimising room for forging and hacking? Or in simpler terms, how to check whether it is a hyperlink click, direct URL, submission of HTML Form, programmatic access etc.?
What about if tools other than PHP is used?
You can't make that bullet proof that way, but a good start is $_SERVER.
For example with $_SERVER['REQUEST_METHOD'] you can determine if the request was get/post/put/...
Regarding link click or direct access: $_SERVER['HTTP_REFERER'] might help.
At last $_SERVER['REQUEST_URI'] might hold some useable info, to determine if the script was run over an webserver (like apache) or the console.
Please see the documentation for more info on that.
And as I mentioned before: You can't be sure of anything here, but if you just want some info, and not use it for security reasons, you are fine.
If you want security you need to look into the possibilities with .htaccess.
It sounds like you might be alluding to cross-site request forgery (CSRF) attacks. CSRF attacks are where an attacker can cause a request to a site that appears to come from a legitimate user (e.g. "Transfer $500 to account 1234."). These attacks abuse the trust that a website has in the visitor. The request might appear legitimate because it is accompanied by a session cookie that matches the user's authentication session.
To prevent CSRF attacks, developers usually add hidden form fields that have "CSRF tokens." This token is submitted with the form submission. It is a means of ensuring form submissions are legitimate. Upon submission, the CSRF token is verified (it is usually compared to the token value stored or computed on the server).
For information on implementation details, check out OWASP. One important note is not to expose tokens in the URL (i.e. through GET requests) as these can expose tokens to potential attackers.
If you have concerns beyond CSRF, please feel free to update your question and I'd be happy to provide additional information that is more specific to your needs.
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.
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.
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.
I have been working on a secure login/portal type set of tools, the general code is free from SQL injections, XSS etc, I have mulitple things in place to stop session hijacking.
regenerate session's ID for EVERY page
Compare the user's IP with the IP at login
compare the user's user_agent with the agent at login
have short session time outs
etc
I have done all I can think of to stop hijacking, however I have still located a situation where it might be possible and would like to know if anyone has any ideas.
Imagine a situation where you have 2 users behind a firewall which does SNAT/DNAT, so both apart to come from the same IP. They are both identical machines supplied by the same place. One connects to the site and logs in, the other copies the PHPSESSID cookie and can simply steal the session.
This might sound like an extreme example, however this is very similar to my place of work, everyone is behind a firewall so looks to be the same IP, and all machines are managed/supplied by the IT team, so all have the same version of browser, OS etc etc.
I am trying to think of another way (server side) to stop the hijacking or minimize it further, I was thinking of a token which gets embedded into every URL (changed for each page), and checked.
I am looking for ideas or suggestions, if you want to offer code or examples you're welcome, but I am more interested in out of the box ideas or comments on my token idea.
Force everything to use HTTPS.
I think you are referring to a passive attack where a user in the network sniffs the cookie. For that, you don't need HTTPS. There are several options that are sufficient when the parties are sure to whom they're talking (e.g. you could do a DH exchange first and the server would encrypt a token the client would use in the next request...), but it's not worth the trouble going down that route.
If the user initially types in a non-https address, an active attack is still possible, but there's nothing you can do in that case. In the future, you might prevent future attacks of this kind once the user establishes one unadulterated connection to your site through HTTP strict transport security..
I wrote the main login portal for a major branch of the U.S. military.
I did all you mentioned above, plus at least one more step:
Have you stored a cookie on first login w/ the SESSION salt? Then encrypt everything serverside using that salt. The crooks would have to know about THAT cookie and STEAL IT, and it dramatically reduces exposure to session hijacking, as they just aren't lokoing for it.
Also, use JS and AJAX to detect if they have flash installed and if they do, store a flash cookie, too, with another salt. At that point you can more or less assume you have some pretty dedicated attackers out there and there's not much more you can do (like sending your users GPG keys to use via javascript and make them sign every single bit of data they send to you).
Do not reinvent the wheal, the built in session handler for your platform is very secure.
There are a number of configuration for PHP's session handler. Use HTTPS, at no point can a session ID be transmitted over http "cookie_secure" does this, its a great feature but a terrible name. httponly cookies makes xss harder because javascript cannot access document.cookie. Use_only_cookies stops session fixation, because an attacker cannot influence this value on another domain (unless he has xss, but thats a moot point).
PHP configuration:
session.cookie_httponly=on
session.cookie_secure=on
session.use_only_cookies=on
I am trying to think of another way (server side) to stop the hijacking or minimize it further, I was thinking of a token which gets embedded into every URL (changed for each page), and checked.
You should look at:
Understanding the Rails Authenticity Token
Tokens are a good idea.