Securing vote buttons like in stackoverflow - php

How Do i secure vote buttons in server-side like here on Stackoverflow? I've seen how the button can be submitted in this answer, But how about in the server side, how do I protect the voting system from csrf attacks and such?

bots generally doesn't run javascript, so just check on server side if it was an AJAX call.
If you want to be more protected maybe append a param generated automatically by javascript with some calc based on current time, then check on your server if it's match with the same calc

A widely accepted way to protect from CSRF is to use a nonce. When the button is clicked and a request is submitted via AJAX or POST data, a nonce value is passed along with it. That nonce is then verified on the backend. You can have that nonce value stored in the session upon generation, possibly using hashing / salting so that the nonce can be specific to a certain action, ie 'vote-up', 'vote-down', etc.
See:
need help understanding nonce

Put a unique id in the GET query portion of each arrow link. That way the attacker / spoofer cannot know to which address to direct the CSRF attack.

The easiest and most effective way is probably to require all users who desire to vote to signup, so that you can keep track of who is voting on each post. As soon as you know who every voter is, you save the user id along with every vote, then you can easily validate that the users hasn't previously voted on a specific question.
Then of course you have to protect your sign up form, to make sure that bots can't register, but that can be done using reCAPTCHA and other similar methods. You will probably also try to limit the users from registering for more than one account. That is of course tricky, but you can at least start of by requiring unique email-addresses for every account, or make use of some third part authentication like Google, Facebook etc.
If you don't want to require sign up, then I guess you have to fallback on registering the IP-address of every vote, but going down that road is trickier. Bots will probably use a whole range of IP-addresses, and you might ending up blocking votes from different users who happens to share the same IP - which can be really annoying.

You can require a Login and even use openid for that.

Related

How to stop people from flooding PHP API with requests?

I am using a simple PHP API that takes requests and connects to a MySQL DB to store/retrieve user information. Example: Login is done using a HTTP POST to the API with username and password.
How do I prevent people from flooding my API with requests, potentially making thousands of accounts in a few seconds.
Thanks
You could serve a token generated and remembered on the server side which is rendered with your forms and validated when the form is sent back to your server. That prevents the user from just generating new post requests without actually requesting the according form from your server since they need the according token generated on your server to get it through.
Then there is the mentioned captcha which would be way too much for a login form from my point but when it comes to things like registering a new user the captcha in combination with the token sounds very good to me.
UPDATE
I Just found this article which is about floot protection of script execution in general. I think their approach is good as is the ip tracking provided you have the ability to use memcache or something similar to speed the checks up.
First, when registering a user, also save her IP address at the time of registration in the DB.
If the IP already exists within 45 minutes of previous registration, reject the request.
Another method is the Captcha, I personally prefer a different method that I found to be even more effective against robots.
Instead of asking the user to "type what they see in an image", and verify they are humans (or robots with sophisticated image processing),
Add another field (for example city), and make it hidden with javascript.
The robots would submit that field to the server, and humans would not.
Note that the robots must run the javascript in order to know what fields are hidden, and this is a time consuming process that they usually don't do.
(see turing halting problem)

I've been asked to perform authentication without usernames and passwords, what are my options?

I've been asked to leave passwords and user names aside since most of the site visitors are stop-buy-come-back-several-months-later-kind of visitors, and the motivation was somewhat along the lines "they would forget there passwords any way and have to request new ones".
I suspect there is no realistic way for me to do this thinking IP:s probably change and browsers get updated, cookies are cleared and so forth.
Or do I have any options?
(not that I'm looking for code but rather concepts and pseudo but the language in the project is php/js coupled with an apache server)
Use OpenID.
Let Facebook, Google, Wordpress, or even Stack Exchange handle the authentication for you, and people wont have to remember another password.
Alternatively:
Many users understand the "forgot my password; check my email" routine by now, so why not just short-cut it by having them input their email and send them a login url with a randomly generated token to log in with.
Once they're logged in, keep them logged in for as long as you deem secure.
We do the following in our e-commerce solution:
We use email as a unique identifier.
When a customer makes a purchase using the same email, the order will be attached to their existing user. You don't however get any address details or stuff like that, but have to enter it manually.
The customer will receive an email with a generated password if it is a first time buy. If it is a second time buy, they will just be instructed to log in. This can however be combined with a url and a login token. Likewise for logging into the site, you could just have them enter an email to receieve a login url token.
Combine this with a long living cookie and/or the browsers datastorage to remember the customers details (address and stuff like that).
Another option would be to have them entering something about themselves that they would always know, but others wouldn't. However it is hard to have an internationally workable solution for this.
You could use so-called supercookies, which is offline storage on the client side. Either through html5 offline storage, or plugin like flash to restore deleted cookies. Although, these cookies is likely to be banned at some point, since they're mostly hidden for the user, and very hard to get rid of. (Not recommending this approach, just saying it's possible)
Authentication credentials break down to three options;
Something you know - passwords
Something you have - physical keys, cards
Something you are - iris, retinal and other biometrics
The best you can do is use cookies I think. Or...I guess you could have them download a file, and upload that file as their access credential - same idea as a cookie but unlikely to be deleted. You would have to think carefully about what to put into the file however - their user id isn't enough, as it would be easily hacked. A random long string would do, one that is saved into the database on their account. Nothing that can be predicted, and nothing that can be used to guess a different account's credential.
A couple of options come to mind:
Use a persistent cookie, but only do this in conjunction with SSL (so it simply can't be sniffed off the wire)
Another option is OpenID like you use here - therefore vistors can use an account they use often to log into your site.
It seems to me that your only option is giving them a forever cookie and hoping it doesn't get purged between visits.
You can read about them here.

Only allow webpage to be viewed via link click

Is there a way to only let a webpage be viewed if the link pointing to it is pressed. I am sending emails to members of my organization with links that attach values to the URL so I can use phps $_GET to figure out who they are on the webpage and update appropriately. What I am worried about is individuals changing the values of the link and changing other members data. If there is a better method for doing this, I am all ears. Using a log in system is not an option.
Not exactly, no.
What you could do is include some token that you keep associated with a particular user id and is very difficult to guess, and include that in the link as well - then, when you get a GET request, you check to make sure the token matches the one you know is correct for that userid. (You'd store the "correct" tokens locally in a database when sending out the emails.)
For instance, you might have...
/modify_info_script?user_id=123&token=aSDqWEqwejk2123salskq
And then you'd have a database table or some other storage that has...
user_id token
----------------------
... ...
122 klqwkejajwie8u8213nak
123 aSDqWEqwejk2123salskq
... ...
and thus if someone tried to change the user_id in the URL, the token wouldn't match and you could reject their request. For instance, this would get rejected...
/modify_info_script?user_id=122&token=aSDqWEqwejk2123salskq
since the right token for 122 would be klqwkejajwie8u8213nak, not aSDqWEqwejk2123salskq.
This is probably the best option if using a login system isn't an option. However, you should really make sure that using a login system isn't an option at all, because user data really should be protected by a login.
This is really not the proper way to secure your site.
However, the simple fix for you is to check the "referer" header and make sure it's not blank. If it's not blank, then it came from a click (or they spoofed it, which is why this isn't secure).
The real way to protect data is to implement a login system with a set of permissions.
To check, if someone came from a link, see $_SERVER['HTTP_REFERER'].
To protect the application against link manipulation, you can combine it with a secret passphrase (only internally, the passphrase must not be known to anyone) and use md5() on the result. Attach the MD5 to the url. If anyone manipulates the url, you will know because the MD5 of "the url plus your passphrase minus the MD5" will be different.
Quite a lot password reset systems work like this so you could say it's reasonably safe provided you use long enough random token. Something like 32 chars should be fine.
Just providing the token should be enough since you don't need the user ID to check it against issued tokens in database.
/modify_info_script?token=aSDqWEqwejk2123salskqfilltill32chars
The other alternative is to have login system where use has to type in their credentials in order to change information.
Also if you really fear that someone might try to guess it, just timeout/ban users after 3 wrong token attempts. No one should be trying to type them in by hand anyway.

Preventing erroneous AJAX Calls by the user

I have a webpage in which the user is awarded X points on clicking a button. The button sends a AJAX request(JQuery) to a PHP file which then awards the points. It uses POST.
As its client side, the php file, parameters are visible to the user.
Can the user automate this process by making a form with the same fields and sending the request ?
How can I avoid this type of CSRF ? Even session authentication is not useful.
You should handle that on the server-side, If you really want to prevent multi-vote or prevent the same people from voting several time on the same subject.
This is why real votes always use authenticated users and never anonymous votes.
By checking the request is really a XmlHttpRequest (with #Shaun Hare response code or with the linked stackoverflow question in your questions comments) you will eventually block some of the CSRF but you won't prevent a repost from the user, using tools like LiveHttpHeaders 'replay' and such. Everything coming from the client side can be forged, everything.
edit* if it's not a voting system as you commented, the problem is teh same, you nedd 'something' to know if the user is doing this action for the first time, or if he can still do this action. There's a lot of different things available.
You can set a token on your page, use that token in the ajax requests, and invalidate this token for later usage server side. This is one way. the problem is where to store these tokens server-side (sessions, caches, etc)
Another way is to check on the server side the situation is still a valid situation (for example a request asking to update 'something' should maybe handle a hash/marker/timestamp that you can verify with current server side state.
This is a very generic question, solutions depends on the reality of the 'performed action'.
Check it is an ajax call in php by checking
$_SERVER['HTTP_X_REQUESTED_WITH']

Protecting Froms From Scriptable Spamming

So I have a form that can create an account and right now the process to create the account is by calling a javascript REST API. I was thinking that it might be really easy to hack that programmatically since all they would need to do it look at the javascript to find out the url to spam and that it might be safer to do the processing in a PHP script. Then I though well, they could just look at the form to find the URL just as easy if I don't do it through javascript. The form is going to be processing only POST data but not sure if that is enough and if it matters if i process it through javascript or PHP.
What it the best way to prevent someone from spamming a form programmatically (ie prevent them from writing server, like PHP, or client, like javascript, code to spams the processing script).
One way is to use Captcha to filter the bots out reCaptcha but its not 100% protection
Using Captcha is probably the first method:
Google's Version
Secondly I would do data checking on the server side and possibly email verification, if the E-Mail is not verified I would have a cron to clean out the rows in your table which don't have e-mail verification.
With these two methods you should avoid a good majority of it.
Go for reCAPTCHA. It's pretty easy.
You can obtain a key pair there by registering your website URL. Use that key to generate the reCAPTCHA image/textbox in your form. Your form's data will be posted and added to database only if entry matches the text displayed in the image, otherwise not (that's aserverside check that you have to keep). You'll get plenty of related code in Google :)
Another technique, as most of the websites now a days follow, is to send an account activation link to the user via email. An account will get created only when that activation link is clicked upon. You can also set an expiration time (say, 24 hours) for this purpose.
Hope this helps.

Categories