Determining a unique user (w/o cookies, ip address) using PHP - php

This is a very broad question; I'm just looking for the best way to do it.
I want to be able to differentiate a unique user. I need to be able to track when a user visits a specific page.
Here are the problems that I and other people have encountered :
Using an IP address is not effective because there might be many computers on an IP address
Using COOKIES encounters a problem if the user clears his/her cookies in a given period of time.
Using SESSIONS encounters a problem if the session expires.
I am considering a combination of all three, but I'm still pretty sure this will not catch all the exceptions. I need a system similiar to the way Youtube tracks views on their videos.
Does anyone have any other ideas to this? (Aside from implementing a user system)

Without using cookies/requiring users to login to identify themselves - determining whether they are "unique" or not will be nearly impossible. There are a few methods to help, but neither are guaranteed:
You can use PHP Sessions - without requiring an actual "user management system".
session_start();
$id = session_id();
The upside to this is, you'll be able to track the current user as long as their session remains active.
The downside is, you won't be able to determine if the "new user" is unique or not if it's an old user who's session has cleared (much like if the user has cleared their cookies).
An alternative, but also along the same lines as using just the IP address, is to attempt a best-possible fingerprinting algorithm using different variables from the $_SERVER environment info:
$userFingerprint = $_SERVER['REMOTE_ADDR'] . ':' . $_SERVER['HTTP_USER_AGENT'] . ':' . $_SERVER['HTTP_ACCEPT']; // plus any others you might find helpful
The upside to this is, there may be enough data to differentiate between users on the same network.
The obvious downside is, there may not be enough data to differentiate between users on the same network.

I think, there isn't any absolute way to do this. Users can change ip address, delete or change cookies etc., because everthing is on their hand.
But according to system (poll, counter) which you are planning, you can develop a way to determine unique user. For example to develop a poll system, you can insert ip, http_user_agent to database and also to increase quality you can set some cookie.

One other way may be to create a table in your database capturing the following data:
IP address
Operating system/ browser etc. (any other info that would
be specific to that user)
Then, you could narrow it down and say, "A user at this particular IP address using this particular OS on this particular browser downloaded this image at this particular time."
Is that what you want to achieve?

Related

Is it possible to identify every separate computer?

I am thinking of a very simple log in system that doesn't require a login, but instead a system with an id and store it in a database. Then when the user comes back to the website he gets matched with his unique ID and logged-in in that way.
I am trying to do this with php as much as possible, initially I wanted to do it by using the IP address but as some people pointed out, places such as campuses share the same IP for many, many users.
So is there any way to uniquely identify each computer without using cookies, sessions or anything else that is client-side. Preferably with php.
No it is completely impossible to do what you are asking. The only theoretical way would be, as you say - the MAC address but it is not sent in web requests.

Are (remember me)s possible for multiple computers?

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.

How to restrict access to web application to one machine only?

I need to make sure that every users accessing my web application can do that from one machine only, so 100 users would mean 100 machines. What would be the best solution? Is detecting and storing IP during first login good idea? I think IP might change even during lifetime of the session is that right? I was also thinking of storing cookie when user first logs in. Then assigning these cookie to the user, same as I do with password and username already, and every time when accessing application checking for presence of that cookie.
Please let me know what in your opinion would be the best solution. My backend is php/mysql if that matters.
EDIT: I need to clarify... This is in addition to normal session management. I need to restrict users to be able to login to web application from one specific machine only. So if user originally logged in from his computer at work and I stored its ip/cookie/etc., then client logs out (or even not), goes home and tries to login won't be able to do that. I agree its horrible idea but client insists :)
IP address might change in the case of mobile clients, or clients that switch between wired and wireless networks. Your best bet would probably be to provide a randomly-generated UID to each client when it first connects (if it doesn't already have the cookie). Then you can check that the same username isn't connecting using two different UIDs.
The trick is that you need to make sure to time this UID out, so that if the user goes to another computer they aren't locked out. Perhaps one change to the UID is okay, but they can't go back to a UID that's already been used?
You can limit to a single useragent by issuing the client with a client side SSL certificate created with the keygen element, this gets the browser to generate a key pair, keeping the private key in the user agent, then you receive an SPKAC, which you can use to openssl create a certificate, which you then send back to the user agent, it installs it and it can be used to identify the user in that specific browser only via HTTP+TLS from then on.
Anything else, simply won't work 100% - although you can hack ways that appear to work (until something goes wrong and it doesn't work) :)
Unfortunately, an IP is not machine-specific for multiple reasons:
The IP address could change during the session, with no notice (the user might not even be aware of it)
Most users have dynamic IP, so it most definitely will change at some point
For machines such as a laptop, tablet or cell phone, the IP address is based on the current service provider
All users behind a proxy would appear to you as a single IP, so you still wouldn't be able to detect if they moved from one machine to another
Instead, generate some kind of unique key for the session and track it in combination with the user name. Prevent them from logging in if the same user name is already in another active session. (You'll also want some way to automatically flush these, just in case you lose the session-end event.)
The best solution is already built into the web server depending on which one you are using. That's what the Sessions are for. In ASP.NET/IIS, usually there is a 20minutes per session timeout.
So if a user uses another computer to access your webapplication, then the session timeout will release connection from the machine that is idle.
UPDATE
You might want to consider restricting user by the MAC Address of their machines which are unique.
If it is a very internal application that will be used only inside a company, it might be possible to define an IP range because smaller companies which do not operate worldwide will probably have a certain amount of IPs from their internet access provider.
You could also think about using some info from $_SERVER to restrict users to a combnation of a single web browser (HTTP_USER_AGENT) and a single port (REMOTE_PORT) - as an additional way to differentiate machines.
But all these solutions are bad or worse, it's technically probably not possible to solve this problem (unless you will have guarantees from your client that all machines will keep a static IP in which case it is a trivial if else problem).
Don't do that. Many people will access your website from multiple computers, and they will complain if you block them.

Setting up a secure polling system

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?

Ways to determine returning "anonymous" guests in PHP

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.

Categories