I'm coding a sweepstakes entry form in php where the User submits some information in a form and it is stored in a database.
I would like to find a way to restrict this form to one submission per person. Either dropping a cookie or by IP address. What would be the best way to approach this?
I'm building it on code igniter, if that makes any difference.
Simple answer, log the IP in the same row with the information store. If you do a cookie a bot or user can easily remove the cookie destroying your protection scheme. So simply log the IP address and then query each entry for uniqueness before accepting the submission.
They both have their own downsides tbh. Cookies are easy to forge and easy to remove which will allow multiple votes. Restricting by IP is better but IP addresses can be shared within networks and can also be proxied to avoid detection. Best bet is rely on something like email address and force the user to click an emailed link to confirm a vote, admittedly though this isn't great.
There are several methods you can use to mitigate against casual cheating. In my view you should not expect to be able to stop a determined cheater without a more formal validation process (cc authorization..etc).
The easiest approach is to ask for a residential address to send goods when they win :)
First and foremost deny the cheater any feedback channel to be able to tell if their submission was accepted or rejected. If there is a slight delay for accepted entries make sure you add a fake delay with some jitter so they can't tell if their scheme for thwarting your anti-cheating method worked or even if you have any anti-cheating methods at all. Detecting bulk submissions by a cheater are much easier when they don't feel they need to be creative.
IP Address as you mentioned. Perhaps use geoip, whois..etc to get distributions over time WRT area.
User agent and system fingerprinting - there is a huge amount of information you can get from the browser that may or may not be unique. Browser type, version, operating system, screen resolution, color depth, installed fonts, plugins (flash, pdf, java...etc) and associated version numbers, language, browsers local time (log client clock skew)
Use of cookies, perhaps hide references to an innocent sounding domain in an included javascript you also control. This may be used to correlate the manual deletion of obvious cookies with the hidden cookies. Its less known that cookies can also be stored in separate databases of other plugins the user may have such as flash player. These are NOT removed when the browser cookies are deleted.
Use of images with cache headers. The first time a user visits the site display an image after their entry is submitted. If they've already filled out the form and they submit again the image would be cached and you can use the absence of the image request to assume submitted entries are a result of cheating.
Why not drop both. Throw a cookie on the user's machine. Then, in a database keep a field with an ip address. That way, if they have different ip addresses (due to certain internet company configs), the cookie can catch it. The database field will serve to be more secure and a backup if people don't allow cookies. These solutions will not be 100% foolproof, however, because if a person had changing ip addresses and doesn't allow cookies, you could run into problems. I would check for cookies being enabled to get around this. Try to set a cookie and read it. If you can, you're good to go. Otherwise, prompt them to allow cookies.
Best of luck
To add to the others, you could require a login/signup to vote.
As stated by others cookies are easy to fake / delete. The client IP seen for a single user can change even mid session, and there may be thousands of users sharing the same client address.
Email addresses are harder to forge - and you can add a verification stage to the process - its information you need to capture anyway - but do keep track of the user agent and client address each submission originates from and is verified from - then you can make a smart determination about the winner instead of trying to check every submission.
C.
Related
The reason I ask is b.c. of this scenario:
A Remember Me cookie is stolen. It is deleted from the stolen computer and placed on the attackers computer. All the models(this one got many upvotes) I have seen would simply treat the attackers computer like the hacked computer and log the person it.
How would one prevent this? I have two ways both unsuitable.
1.) Only allow only one Remember Me Computer.
2.) Track multiple computers and have the user monitor how many computers have him / her remembered.
Is there a way to track something hard on the computer like the Ethernet MAC address perhaps?
EDIT ANSWER:
Use a MAC address. Below link provides external component for IE and Firefox. Need an external component for Safari.
SO Solution
ADDED FOR CLARIFICATION:
Not IP Addresses (hard as in something that can not change)
Save in the cookie hash of the User Agent + something else (like resolution). Maybe not very secure but better than simple cookie with remember me information and would work for people with dynamic IPs.
Change the cookie on every login/visit. If the computer is stolen, you log in and the cookie changes. Stolen computer has old cookie gets logged out.
If the stolen computer logs in then he/she changes the cookie. The real user gets logged out, and then has to log back in which changes the cookie again.
Tie the cookie to an IP address, server side?
You can set the last remember me loged in ip into a database (or into the cookie)
$_SERVER["HTTP_CLIENT_IP"]
My approach to this would be a hybrid of various techniques. I'd use cookies containing information about the PC that had been logged in - Browser, Resolution, etc, as well as (by default) the IP. Obviously I could match these against the last values recorded in the database to ensure the machine with the cookie hadn't changed.
I'd then provide a method for those with dynamic IP addresses to opt-out of IP address matching for the sessions, with plenty of appropriate warnings that doing so would significantly decrease the security protecting their account, of course.
I like to look at Windows Live Messenger in this instance, if I log into the desktop app as well as hotmail I get a notification that I'm logged into more than 1 place - it asks me if I want to log out of the other location.
What I like about this is it puts control into the users hands, what I don't like about this is an attacker can kick out a genuine user and completely hijack an account.
This whole topic to me looks like you're damned if you do and damned if you don't.
Lets just take a step back for a minute, who can be an attacker? Well anyone really - take for example your ex-husband or ex-wife who knows your usernames and passwords, he/she can easily attack your account because he/she knows all of your information to start with. You can never completely protect yourself, you change your password but he/she probably knows that too!
I ask you to look at your project and evaluate if a remember me system would actually deliver added value over any security risk it poses.
Now, the direct answers for your questions:
Generate a unique key for the user, insert it into your database and write the key to your cookie, when the cookie is sent to the server you evaluate it against the key in the database, if it is a match - bingo, you have access, if not run a logout script and destroy the cookie.
For this, each time you write a cookie store the information in your database against a user ID and status of the cookie (e.g. alive or dead), then each time you read the cookie check the status of it - if it is set to alive then simply log the event and move on but, if it is set to dead you kill the cookie and log that it was killed.
Next you can display this log information and give certain controls to the user, for example you can allow the user to set a cookie to dead then next time you read the cookie you kill it.
Working with hardware is easier said then done but it is doable. The easiest way I have found is to use a Java applet that is run locally, you can then detect hardware information and send it to your application for processing. For your average website I don't personally think it's worth it but it is doable.
Another alternative is to wrap your application in something like Adobe AIR that can detect the hardware information for you to work with.
I hope this helps you.
I'm creating a web application where users will vote for some candidates by clicking thumbs up or thumbs down, and these users won't have any account on the site.
What is the best technique to use? Is it necessary to use captcha for more protection from spam?
Vote counts are expected to be millions, and the subject is not very critical as long as I get 95% accuracy that would be fine. Thanks.
You can combine these two methods:
Add a cookie to prevent multiple votes from the same machine
Log IP addresses and prevent voting more than a set number of times from the same address (for example, 5 times the same hour).
This will make it possible for multiple persons to vote from the same network but still prevent excessive cheating.
You may also make it harder to build a voting bot by adding some hidden form field with a token that must be included in the vote, and/or use Ajax for the voting. I know it's relatively easy to build a bot anyway but most cheaters aren't that smart.
Cookies and Session Ids will help, although both can be lost when the browser is closed (if the user has it enabled to delete them). Still, they will give you some degree of accuracy (ex. the lazy voters won't bother to close and reopen their browsers).
Using IP Addresses would also work, but as #Michael Dillon said people on the same IP address (same router) will not be able to vote.
You have several options, some or all of which you can use.
You can record IP and then check against IP, but then this isn't indicative of a specific person just a computer and sometimes not just a single computer.
You can also write a cookie to a user's browser but a user can use a different browser, machine etc.
Within a user's session you could create a session variable, although if you are expecting very high traffic this may not be the best option, and also only prevents re-voting within the same session.
If you are contemplating a captcha, you may as well ask the user to supply an email address and then you are assured of at least one vote per email address. However, even then you cannot be guaranteed valid email addresses.
You can ask their phone numbers when they want to vote and send to them one time password and use that as verification.
Some my also vote from another numbers but i think this is the most accurate way.
I am about to write a voting method for my site. I want a method to stop people voting for the same thing twice. So far my thoughts have been:
Drop a cookie once the vote is complete (susceptible to multi browser gaming)
Log IP address per vote (this will fail in proxy / corporate environments)
Force logins
My site is not account based as such, although it aggregates Twitter data, so there is scope for using Twitter OAuth as a means of identification.
What existing systems exist and how do they do this?
The best thing would be to disallow anonymous voting. If the user is forced to log in you can save the userid with each vote and make sure that he/she only votes once.
The cookie approach is very fragile since cookies can be deleted easily. The IP address approach has the shortcoming you yourself describe.
One step towards a user auth system but not all of the complications:
Get the user to enter their email address and confirm their vote, you would not eradicate gaming but you would make it harder for gamers to register another email address and then vote etc.
Might be worth the extra step.
Let us know what you end up going for.
If you want to go with cookies after all, use an evercookie.
evercookie is a javascript API available that produces
extremely persistent cookies in a browser. Its goal
is to identify a client even after they've removed standard
cookies, Flash cookies (Local Shared Objects or LSOs), and
others.
evercookie accomplishes this by storing the cookie data in
several types of storage mechanisms that are available on
the local browser. Additionally, if evercookie has found the
user has removed any of the types of cookies in question, it
recreates them using each mechanism available.
Multi-browser cheating won't be affected, of course.
What type of gaming do you want to protect yourself against? Someone creating a couple of bots and bombing you with thousands (millions) of requests? Or someone with no better things to do and try to make 10-20 votes?
Yes, I know: both - but which one is your main concern in here?
Using CAPTCHA together with email based voting (send a link to the email to validate the vote) might work well against bots. But a human can more or less easily exploit the email system (as I comment in one answer and post here again)
I own a custom domain and I can have any email I want within it.
Another example: if your email is
myuser*#gmail.com*, you could use
"myuser+1#gmail.com"
myuser+2#gmail.com, etc (the plus sign and the text after
it are ignored and it is delivered
to your account). You can also include
dots in your username (my.user#gmail.com). (This only
works on gmail addresses!)
To protect against humans, I don't know ever-cookie but it might be a good choice. Using OAuth integrated with twitter, FB and other networks might also work well.
Also, remember: requiring emails for someone to vote will scare many people off! You will get many less votes!
Another option is to limit the number of votes your system accepts from each ip per minute (or hour or anything else). To protect against distributed attacks, limit the total number of votes your system accepts within a timeframe.
Different approach, just to provide an alternative:
Assuming most people know how to behave or just can't be bothered to misbehave, just retroactively clean the votes. This would also keep voting unobtrusive for the voters.
So, set cookies, log every vote and afterwards (or on a time interval?) go through the results and remove duplicates based on the cookie values, IP/UserAgent combinations etc.
I'd assume that not actively blocking multiple votes from same person keeps the usage of highly technical circumvention methods to a minimum and the results are easy to clean.
As a down side, you can't probably show the actual vote counts live on the user interface, or eyebrows will be raised when bunch of votes just happen to go missing.
Although I probably wouldn't do this myself, but look at these cookies, they are pretty hard to get rid of:
http://samy.pl/evercookie/
A different way that I had to approach this problem and fight voting fraud, was to require an email address, then a person could still vote, but the votes wouldn't count until they clicked on a link in the email. This was easier than full on registration, but was still very effective in eliminating most of the fraudulent votes.
If you don't want force users to log, consider this evercookie, but force java script to enable logging!
This evercookie is trivial to block because it is java script based. The attacker would not likely use browser, with curl he could generate tousends of requests. Hovewer such tools have usually poor javascript support.
Mail is even easier to cheat. When you run your own server, you can accept all email addresses, so you will have practically unlimited pool of addresses to use.
I'm currently in charge of setting up a polling system (using PHP).
Now for it to be as secure and objective as possible, it's important that a visitor can only vote once. I'm thinking of validating the polls by visitor's IP (there can be only one vote from one IP), and maybe throw in a captcha test to be sure that no bots can get in once they've passed the IP validation for some reason.
So there it is, unique-IP validation and captcha. But is this enough ? Is there a possibility that a single user can change his/her IP by using proxies or other ways I don't know of, and vote multiple times with unique IPs ?
Are there better ways to do this ? Preferably without the captcha.
Thanks in advance.
There is absolutely no way to be sure a user has voted once when it's a public voting system, where no login is required.
Checking the IP is not a good idea for several reason. As described in other answers, lots of networks are behind one ip, and users can just use an other pc with different ip and vote again.
OpenId
Use OpenId to identify the user and check if they have already voted.
Register users
Optionally you could allow users to register themselves if they do not have an openid account.
To implement a secure system, where session spoofing, and thus multiple voting, is made difficult read this
You can't create a 100% secure voting system.
If it's based on registration/IP/cookie, the user can create a new user/get an another PC/delete all cookie.
But you can try it with auto prefilter + administrator as postfilter workflow:
Prevent multiple voting with cookie (or IP / browser properties / etc.) filtering automatically.
On an admin view, the administrator can parse and delete votes by hand based on IP or subnet address. This is nor a perfect solution, but with some good query (same votes in the same time intervall from the same IP/subnet) the administrator can easily delete suspicious votes.
One big drawback of this solution is the need of an administrator. But - I think - there is no perfect solution.
Unless you're going to require identity verified by CA, there is no way you can be sure, that each person votes only once. This of course would be total overkill, so the real question is: how to make multiple votes more difficult.
email with verification code. IMHO overkill, but depends on how sure you want to be.
use session to check who voted. Obviously not 100% secure, but will stop 99% of ppl.
use cookie to check who voted. Like above, some ppl will know how do delete cookies.
use POST, ignore GET.
use combination of 2 or 3 of above.
If you're going to use IP for validation, do not use just REMOTE_ADDR, combine with whole X-Forwarded-For. This way you won't block people connecting through same proxy.
Don't go with the way of unique Ip. There are a lot of case scenario where a lot of users have the same ip (i.e. italian isp fastweb, large corporations, etc). Also, if user has dynamic ip it can change it's own ip address every time he likes...
One of the best ways should be using email address and cookies. User will be able to vote multiple times (you can't avoid this), but at least it will take them some time for each vote.
for a similar project i did 2 verifications ...
i placed a cookie and also saved on the server a hash from users ip + user agent.
this seemed to be pretty effective since even if there are more people that use the same IP the hash with user agent will be different most of the times since it differs for same browser depending on the operating system and other extensions installed.
There is no fool proof way for preventing multi votes. Checking cookie is anothr option.
Regarding Validatin the ip address. What if the user is from a net work which is used by many users?
Two types of users visit my website: registered users and guests. Registered users are tracked and retained by PHP session, cookies and individual logins. Guests I find trickier to manage so I give little to no authority to contribute content.
I want to open up editing for users (registered or not) to save favourites, shopping carts, vote in polls, moderate, tag, upload and comment. At the same time, protect the data from other non-registered users.
What are some options or best practices to determine a unique visitor from another and some security measures to consider when allowing them to contribute more? Should I work around their security/restriction settings to provide contribution service or should I expect them to meet in the middle and relax some of their settings to allow cookies etc?
IP Address - The IP is an option but only temporary. It can change for a user reconnecting to their Internet with a different IP, and for that matter another user may eventually share the same IP. IP can also be anonymous, shared or misleading.
PHP Sessions - OK for a session (and if enabled) but lost on closing the browser.
Cookies - Can store session data but is easily (and often) disabled from the client-side.
Header data - combining known details of he user might at least group users - ISP, browser, operating system, referring website etc.
Edit: I'm still having trouble getting my head around all the the key factors involved... we set up a cookie for a guest. Attach a bunch of edits and user history to that session. If the cookie is removed, the data floats around attached to nothing and the user loses their data. Or if the user logs in, the guest and user data should be merged...
I think cookies would probably be the best option here as it's the only way you are going to be 100% sure requests are unique. Of course, you could possibly add a mix: if cookies are disabled you might be able to try other options of identification such as the IP address method, but that could make it overly-complex.
As you say, IP address is liable to change and in some organizations there may be a group of proxy servers setup which make requests originate from different IPs. Of course, you could check X_FORWARDED_FOR, but they are still liable to change.
Header data is probably going to prove difficult to get good results on I think. If you've got an organization that has the same browser, OS, IP it is going to show people as being the same. Even people not in the same organization may still appear similar (i.e AOL users who get their traffic usually routed through proxy servers, the majority will probably be using the 'AOL browser' that gets shipped with it giving similar headers).
Out of those two options, the IP one is going to be easy to implement but obviously there are the problems I outlined. Checking for unique data in the headers will prove to be absolute pain I think.
Obviously as you say, sessions are lost on closing the browser, and it appears you want the system to behave as if they were a registered user so cookies seem a more obvious choice (especially as you want the 'favourites' to be persistent).
I would just go with sessions.
Your users could change IP addresses (prone to mixup behind NATs and proxies), modify/delete cookies (certainly possible), or change their header (easily through switching browsers).
There is no secure way of identifying a guest if they do not want to be identified. Just go with the standard: cookies/sessions.
You should use sessions.
Sessions id are stored in a cookie (or for users who doesn't accept cookie, stored in the url with the PHPSID argument)
They won't be erased when the user will close his browser, it just depends on how you set your session/cookies options.
You can set up the timelife of a session to whatever you want, so don't bother with this.
You should also tell to your user about this (enable cookie)
Concerning the data which could be merged when log in, it's your job, to merge it in a proper way, or even ask the user if the option should be saved or not.
You could use a combination of all of the identifying points that you can find, that are not likely to change, and are likely to be unique - looking at panopticlick you can gather a bunch of data such as installed fonts and browser plugins. You could take those kinds of more unique data points and hash them to give you an id, and then compare it against the less unique data like useragents and ip addresses.
But honestly, that's super complicated and sneaky. Use cookies/session. If the user doesn't want to enable cookies then they don't want all your anonymous tracking for a reason, and you should honor their decision.