2

The use case

Currently, I am trying to build a page where users can vote on content (up/downvote, similar to the function on the StackExchange network). But the users shouldn't need to register themselves to vote on content. So it would be a kind of "anonymous" voting page. It is built with Laravel5 and uses a MySQL database to store the votes. The user sessions are stored in flat-files, but can be also stored in a database table (L5 is quite flexible here).


The problem

How to make it secure?.

I am storing restrictions and already voted contents in the user sessions, e.g. when the user has voted on content XYZ (so the user cannot vote again on the specific content for now). Those restrictions are time-based, mostly 24 to 48h. This works well, as long as the user does not throw away/delete his cookies, which would cause to create a new session and remove the time restrictions, which could lead to easy vote fraud.

So, how to avoid that the user "loses" his session? The focus is on how to let the restrictions and limitations of each "anonymous" user persist! Shared PCs or voting on different locations cannot be avoided when voting anonymous, but "botting" or a vote fraud in large numbers needs to be avoided with a given solution.


Solution attempts

Setting the sessionId of each users session to a combination of IP and User-Agent

I've asked a question about this attempt (linked below), but it'd open up more problems then it'd solve (e.g. easy session spoofing). Also, I couldn't achieve to set the sessionID manually by using Laravel5.


Solutions that doesn't fit

  • Let every user register themself (it's simply too much effort for each user in my use case)

Related

Community
  • 1
  • 1
manniL
  • 7,157
  • 7
  • 46
  • 72
  • Do something with IP-address maybe? – Refilon Dec 19 '16 at 09:47
  • With so many devices available per user, and anonymous browsing supported by most browsers these days, personally, I believe just setting a cookie (which is not session based) would be the only way to achieve this and keep the user actually anonymous (not collecting data which could personally identify them). – William Isted Dec 19 '16 at 09:47
  • @Refilon Please read the "Solution attempts" section. Already tried this. The related SO question can be found on the bottom. – manniL Dec 19 '16 at 09:48
  • @WilliamIsted But what happens when the user deletes his cookies? All "restrictions" are lost/gone then.. – manniL Dec 19 '16 at 09:49
  • @manniL yes, that's the same outcome as if a user chooses to use "Private browsing" or Incognito, or they differ by mobile vs the PC when they come back to your site. There's few ways without getting to Google and other Ad publishers levels of varied data collection that could ensure the user remains anonymous. You could allow the user to create a login, with only a username (may randomised) and password, without needing an email address. Then keep the voting times within your DB, but this depends on if this is anonymous enough or not for your use. – William Isted Dec 19 '16 at 09:54
  • There's no practical way of preventing the user from deleting the session cookie. So long as you have anonymous voting you'll always have a problem of either ballot-stuffing or preventing people from voting because somebody else who happens to match some criteria of theirs has already voted. – GordonM Dec 19 '16 at 09:55
  • @WilliamIsted The problem is not the anonymity of the user, but the persistence of their restrictions. When the user deletes the cookies, goes into private browsing or does similar things, the vote restrictions are gone. A login is unfortunately no option. – manniL Dec 19 '16 at 10:06
  • @GordonM That's what my research results are too. But in my case, preventing a low percentage of people from voting is better than leaving the option of vote fraud open to everyone. – manniL Dec 19 '16 at 10:07
  • @manniL Well you could always log their IP, but this raises privacy concerns (even if hashed the IP data could potentially be tied to a specific user, V4 IPs are short enough that brute-forcing them even with a strong hash isn't out of the question), and it still wouldn't solve problems like a user with a smartphone voting several different times from different locations, going to libraries and internet cafes, etc. You might just have to accept that there's going to be a degree of fraud no matter what you do unless you forbid anonymous voting – GordonM Dec 19 '16 at 10:11
  • @GordonM Well, using different devices/different locations and so on is a degree of "vote fraud" that is certainly unavoidable and I have to deal with. Anyway, it's nothing in comparison to vote-fraud by using a bot or similar tools, which I want to restrict as good as possible. – manniL Dec 19 '16 at 10:14
  • 1
    @manniL For your reference; there are many techniques out there that people and companies practice to try to ensure that one user is the same as before. https://en.wikipedia.org/wiki/Canvas_fingerprinting in your case "A software developer writing in Forbes stated that device fingerprinting has been utilized for the purpose of preventing unauthorized access to systems long before it was used for tracking users without their consent." seems to be relevant, but this method still isn't full proof despite the further ability to collect machine configuration. – William Isted Dec 19 '16 at 10:19
  • @manniL Well it might be possible to rate-limit on IP address without actually storing them long-term (A bot attack will probably submit requests every few seconds as opposed to a few times per hour for a human fraudster). Or you could use something like a CAPTCHA to protect against bots (though they carry their own set of issues, not least accessibility). Or you could simply use weighted voting and give votes from registered users more weight than from anonymous users when deciding how to tally votes (for example anonymous votes are worth 1 point, registered users worth 10, etc) – GordonM Dec 19 '16 at 10:20
  • @WilliamIsted This sounds quite interesting! Maybe a combination of different methods can provide a good protection. – manniL Dec 19 '16 at 10:23
  • @GordonM Throttleing votes of a distinct IP and displaying a CATPCHA when the vote count is higher than normal are things that I've already built-in. Haven't mentioned them yet because it's no direct protection against loosing a session, but one against bots. – manniL Dec 19 '16 at 10:25
  • @manniL That depends on your perception of "good" – William Isted Dec 19 '16 at 10:25
  • @WilliamIsted Haha, yeah. That's true. I also thought about implementing [evercookie](https://github.com/samyk/evercookie) for my purpose. – manniL Dec 19 '16 at 10:29
  • one way: if they don't have a cookie then send them a 'captcha'. i.e. having a cookie you can work out what they did. Now, if they don't have a cookie then they have to fill in the captcha each time. Most people will get bored and so those that are persistent will be unlikely to affect the overall results significantly? – Ryan Vincent Dec 25 '16 at 16:11
  • @RyanVincent That's also a great idea! – manniL Dec 25 '16 at 16:13

2 Answers2

1

as users are not stored and maintained its very difficult and can't be made 100% sure.

how i try to achieve this most closely is using request ip address and csrf token. you can get ip address from request and csrf_token() from anywhere inside your laravel application.

here is an example of how i am going to implement

create a table named votes having following fields

  • votable_type
  • votable_id
  • ip_address
  • csrf_token

i would check whether a client does not have an existing record for same votable type and id. client is a the csrf_token. ip is for guaranteeing whether the requests are legit.

votable type and id is the polymorphic relationship between either may be comments, posts etc.

note

without persisting user identification in anyway some users might not be either vote or some might vote twice. it can't be done perfectly.

  • some users might vote from different user agents multiple times.
  • some users might spoof ip. clear cookies
  • different users might be using same system to login.
  • some users might be using different connections or system logins.

so either we take any information it wouldn't be 100% accurate.

Community
  • 1
  • 1
aimme
  • 6,385
  • 7
  • 48
  • 65
  • This method would have problems with entities that have shared computers in a public space i.e. Libraries, Schools, Universities, Offices etc... It would likely depend on the demographic of the users that would be voting. – William Isted Dec 19 '16 at 10:04
  • you mean csrf token would be same? – aimme Dec 19 '16 at 10:05
  • csrf would be different, but if a user moves from one PC to another through the day, they may be able to vote again if the cookie is not kept on the domain login – William Isted Dec 19 '16 at 10:07
  • I guess that the csrf token won't be the same when the user deletes his cookies. – manniL Dec 19 '16 at 10:10
  • same way another person may be using same system. so he can't vote either :) – aimme Dec 19 '16 at 10:10
  • As stated in the comments above, shared pcs or users who can't vote are a small part of my target group and are "acceptable" problems. Botting or vote fraud in large numbers is not. That's why it'll be problematic using your solutions because the csrf token resets. – manniL Dec 19 '16 at 10:16
  • both ip address, csrf token and even you can get user agent. single entity can't determine whether its legit. – aimme Dec 19 '16 at 10:18
  • @aimme At least a combination of them is needed, I know – manniL Dec 19 '16 at 10:25
  • @manniL ya..thats what i am saying. ip is used to make sure the request is legit :) – aimme Dec 19 '16 at 10:34
0

My solution was combination of implementing evercookie to assign a "Identification Cookie" per user, detecting privacy browsing and restrict access when having Incognito mode or private browsing enabled, and finally restrict several actions (voting in my case) when not having the evercookie.

Community
  • 1
  • 1
manniL
  • 7,157
  • 7
  • 46
  • 72