I don't run a mission critical web site so I'm not looking for an industrial strength solution. However I would like to protect against basic attacks such as someone mocking up a false page on the hard disk and attempting to gain unauthorized access. Are there any standard techniques to ensure that form submission is only accepted from legitimate uses?
A few techniques come close:
Produce a form key for every form. The key would relate to a database record, and something else unique about the page view (the userID, a cookie, etc.). A form cannot be posted if the form key does not match for that user/cookie. The key is used only once, preventing an automated tool from posting again using a stolen key (for that user).
The form key can also be a shared-secret hash: the PHP generating the form can hash the cookie and userID, for example, something you can verify when the form is posted.
You can add a captcha, requiring a user to verify.
You can also limit the number of posts from that user/cookie (throttling), which can prevent certain forms of automated abuse.
You can't guarantee that the form isn't posted from disk, but you can limit how easily it is automated.
You can't. There's no reliable way to distinguish between an HTTP request generated from a user on your page, or a malicious user with their own web-page.
Just use a proper password authentication approach, and no-one will be able to break anything unless they know the password (regardless of where the HTTP requests are coming from). Once you have reliable server-side authentication, you don't need to waste time jumping through non-robust hoops worrying about this scenario.
You should not create a login-system yourself because it is difficult to get it right(security). You should NOT store the passwords(in any form whatsoever) of your users on your site(dangerous) => Take for example lifehacker.com which got compromised(my account too :(). You should use something like lightopenid(as stackoverflow also uses openid) for your authentication.
The remaining forms you have on your site should have the following protection(at least):
CSRF protection: This link explains thorougly what CSRF is and even more important how to protect against CSRF
Use http-only cookies: http-only sessions, http-only cookies
Protect against XSS using filter.
Use PDO prepared statement to protect youself against SQL-injection
i also recommend:
Save the IP of the computer that sends the form (to block it from the server if it.s annoying)
Use CAPTCHA when required, to avoid robots...
Send users to another page when the info is loaded, so the POST data won't be retrieved when you refresh the page.
Proper validation of form data is important to protect your form from hackers and spammers!
Strip unnecessary characters (extra space, tab, newline) from the
user input data (with the PHP trim() function)
Remove backslashes () from the user input data (with the PHP
stripslashes() function)
for more detail, you can refer to Form Validation
Related
What is the best way to protect again CSRF attacks in PHP.
It has been recommend to use form tokens, so basically generate a random value and store it in a hidden field. Then also store this random value in the users session.
Finally in the form action, make sure the session and form token match.
if($_SESSION['token'] !== $_POST['token']) {
die("bad... spanking...");
}
Is there a better/easier way, as this requires a lot of code modification in my application (lots of forms and actions).
No. To protect against CSRF, you need to make sure you only trust credentials that are automatically appended to requests (like cookies) when you have reason to believe that the user actually submitted your form. The only way to do that is to have the form carry some kind of secret that the server uses to authorize processing.
If you use a framework or library to compose your form it might help by generating the random number, setting the cookie or session property, and adding the hidden input to your form but those three steps do need to happen.
How can I prevent users from forging forms on the PHP or jquery side, I am using Jquery's ajax functionality to submit the forms, and this means that tech-wise people can change some variables such as the value of something (that shouldn't be changed / is a user id or something like that) through the use of firebug or web inspector and likewise.
So how can I prevent users from changing these variables or making sure they are unchangeable through a secure and good way?
Thanks
As the others have already stated, you can't prevent the user from tampering.
You are receiving data from me, and I can send you anything I want, I can even do an HTTP request by hand, without even using a browser, and you can't do anything about it.
If you don't want a user to be able to alter an information, don't provide it to him.
You can store it in PHP's session, which is stored server side (do not use cookies, they too are sent to the user) or save it in a database, both of them are not accessible to the end user.
If you still want to pass the data to the user, compute some sort of hash (a secure hash, using a secure hashing algorithm and a secure message digest as Gumbo noted, this rules out algorithms like CRC32 or MD5 and MACs like your name or birthday) of the data and store it server side, then when the user submits back the data, check if the hashes match.
But do know that this solution is not 100% secure. Hashing functions have collisions, and bad implementation exists.
I would recommend to stick to the golden rule: if it's not there, it cant break / be tampered / be stolen / etc.
You cannot prevent users from doing so.
Store these variables in a Session.
You can never trust the client. Validate the form on the server to ensure the data is sane. This means checking that a given user ID has permissions to post their form, etc.
I'm going to go with... you can't. You never trust the user's data; client side verification is always only the first line of defense.
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 use $_POST to read data sent through HTML forms to the server, narrowing down attacks exposure.
How can I strengthen security, using some kind of tokens in the form?
The tokens could be readable however with a sniffer.....
**** EDIT *****
I agree the message above is generic...I'll try to give more details!
Ok, a PHP/Server generates emails containing some data for a sort of user-revision; this is accomplished with an HTML email containing HTML forms. When users receive those emails, they edit data in the forms, and send it back to the server, that in turn it will store it in the database.
While for other types of interaction users/server, login/authentication is required, in this case some particular email clients, like mobile phones, do allow reading HTML email messages and process forms, unfortunately without allowing client authentication (server side login) prior processing the form.
What happens on the server side when forms are received?
Well $_POST is used, removing potential GET weakness, however using $_POST will not prevent other kind of attacks, just because a sniffer can easily "read" data being sent.
Data on the server side is parsed and stripped accordingly, removing unsafe Javascript and quoted text to prevent injections and other sort of attacks.
That's why I was looking for a sort of token/nonce technique, however I thought that tokens are sniffable within the form..... and that's where my help request starts!
You are probably refereing to CSRF (Cross site request forgery). Chris Shiftlett wrote an article about it which explains the concept.
Here are a few things you should look into.
SSL Certificates
CSRF Protection
Ok, I have discovered that Wordpress offers it's own API for NONCES.
What I do now is to add an input field in the form containg the NONCE; when user sends form to the server, the NONCE is validate back.
There's a little chance an attacker could gain access using NONCE contained in the form ** ONLY ** during the lap time occurring between NONCE issue/verify. Quite difficult though: the attacker should sniff data, grab the NONCE and use it immediately to load "something" in the database...
What could it be loaded, assuming content is being stripslashed and de-javascripted?
Moreover, as WP NONCES are created using constants:
wp_create_nonce ('my-nonce');
this will require some additional tasks to use variable generated NONCES in such a way for the attacker it will be more difficult to track the pattern to generate the NONCE...
What do you think?