SitePoint Sponsor

User Tag List

Results 1 to 20 of 20
  1. #1
    SitePoint Addict Hero Doug's Avatar
    Join Date
    Nov 2003
    Posts
    250
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    Idenfitying Users without using a cookie

    I did a quick search and didn't turn up much. Anyways the goal is to identify users without using cookies.

    I was thinking of using the following server variables which *should* provide a unique fingerprint, but I feel it's still not unique enough.

    Code:
    echo $_SERVER['HTTP_ACCEPT'] . "<br />";
    echo $_SERVER['HTTP_ACCEPT_CHARSET'] . "<br />";
    echo $_SERVER['HTTP_ACCEPT_ENCODING'] . "<br />";
    echo $_SERVER['HTTP_ACCEPT_LANGUAGE'] . "<br />";
    echo $_SERVER['HTTP_HOST'] . "<br />";
    echo $_SERVER['REMOTE_ADDR'] . "<br />";
    echo $_SERVER['REMOTE_HOST'] . "<br />";
    I'm wondering what else I could add to help ensure it's unique. Any ideas?

  2. #2
    Theoretical Physics Student bronze trophy Jake Arkinstall's Avatar
    Join Date
    May 2006
    Location
    Lancaster University, UK
    Posts
    7,062
    Mentioned
    2 Post(s)
    Tagged
    0 Thread(s)
    I see two options. One would be to use sessions - but instead of the user having a cookie set to identify them, I think it's possible to append it at the end of urls, when the user clicks a link.

    The other option is that a user logs in via a .htaccess security "AuthType", which opens a sub-window for them to login to. The user is then identifiable by accessing $_SERVER['REMOTE_USER'];
    Jake Arkinstall
    "Sometimes you don't need to reinvent the wheel;
    Sometimes its enough to make that wheel more rounded"-Molona

  3. #3
    SitePoint Zealot cholmon's Avatar
    Join Date
    Mar 2004
    Location
    SC
    Posts
    197
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Are you trying to ensure uniqueness just within a single session (i.e., across page requests) or also for returning visitors?
    Drew C King: PHP Developer
    <?= $short_tags++ ?>

  4. #4
    Programming Since 1978 silver trophybronze trophy felgall's Avatar
    Join Date
    Sep 2005
    Location
    Sydney, NSW, Australia
    Posts
    16,604
    Mentioned
    24 Post(s)
    Tagged
    1 Thread(s)
    For returning visitors your choices are:

    1. cookie
    2. cookie
    3. forget about it

    Within the one session your choices are

    1. session cookie (never actually written to a file)
    2. pass the session in a query string
    3. frames
    Stephen J Chapman

    javascriptexample.net, Book Reviews, follow me on Twitter
    HTML Help, CSS Help, JavaScript Help, PHP/mySQL Help, blog
    <input name="html5" type="text" required pattern="^$">

  5. #5
    SitePoint Addict Hero Doug's Avatar
    Join Date
    Nov 2003
    Posts
    250
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by cholmon
    Are you trying to ensure uniqueness just within a single session (i.e., across page requests) or also for returning visitors?
    This is for a single session, not for return visitors. And I forgot to mention one thing, this is for a distributed site, not something running on a shared account.

    Quote Originally Posted by arkinstall
    I see two options. One would be to use sessions - but instead of the user having a cookie set to identify them, I think it's possible to append it at the end of urls, when the user clicks a link.
    It is possible, but this opens the door to some odd backlinking behaviour. If the user goes to visit the page of an expired session it may result in an error of some sort.

    Quote Originally Posted by arkinstall
    The other option is that a user logs in via a .htaccess security "AuthType", which opens a sub-window for them to login to. The user is then identifiable by accessing $_SERVER['REMOTE_USER'];
    Sounds like a possibility, I'm not sure how difficult it'll be to syncronize multiple servers though. I'd actually like to read a little more about how it works. It may be a good approach to mimic.

    Quote Originally Posted by felgall
    Within the one session your choices are

    1. session cookie (never actually written to a file)
    2. pass the session in a query string
    3. frames
    I'm still putting my origional idea on the list as #4. A cookie can be downloaded, studies, and possibly used as a tool to hack into a site.

    The more information that has to be validated the harder it'll be to forge someone elses information.

    That's why I'm asking what other way's there are (using PHP) to get additional information about a user. Maybe there's a library or function I'm overlooking.

  6. #6
    Programming Since 1978 silver trophybronze trophy felgall's Avatar
    Join Date
    Sep 2005
    Location
    Sydney, NSW, Australia
    Posts
    16,604
    Mentioned
    24 Post(s)
    Tagged
    1 Thread(s)
    Store the info about each visitor in a database. Store a unique string of random characters in a field of each visitor's record. Store that unique string only in a cookie on their computer. There is then no useful information in the cookie unless they also break into your database.
    Stephen J Chapman

    javascriptexample.net, Book Reviews, follow me on Twitter
    HTML Help, CSS Help, JavaScript Help, PHP/mySQL Help, blog
    <input name="html5" type="text" required pattern="^$">

  7. #7
    SitePoint Zealot cholmon's Avatar
    Join Date
    Mar 2004
    Location
    SC
    Posts
    197
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    You could create a pseudo-session ID on the server side by creating an MD5 hash of those relevant $_SERVER values at the beginning of each request, something like:
    PHP Code:
    <?php
        $info 
    $_SERVER['HTTP_ACCEPT'] . "|" .
            
    $_SERVER['HTTP_ACCEPT_CHARSET'] . "|" 
            
    $_SERVER['HTTP_ACCEPT_ENCODING'] . "|" 
            
    $_SERVER['HTTP_ACCEPT_LANGUAGE'] . "|" 
            
    $_SERVER['HTTP_HOST'] . "|" 
            
    $_SERVER['REMOTE_ADDR'] . "|" 
            
    $_SERVER['REMOTE_HOST'];

        
    $uid md5($info);

    ?>
    But that is also a bit flaky. Imagine having two identical machines (same OS, same browser config) sitting behind a firewall. It's very much possible that two different users on two different machines in that type of environment would look 100% identical to your web app.

    The only way to truly ensure uniqueness is with some client-side functionality, either with the help of cookies or with HTTP authentication like arkinstall suggested. You can probably deal with distributed server-side HTTP authentication if you rely on a database-connected authentication module, something like mod_auth_mysql.
    Drew C King: PHP Developer
    <?= $short_tags++ ?>

  8. #8
    SitePoint Wizard Hammer65's Avatar
    Join Date
    Nov 2004
    Location
    Lincoln Nebraska
    Posts
    1,161
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    This problem pops up with online polls all the time. The only way to determine that a person has already voted is a cookie. If you do it by IP or any other system, you can run into a problem where multiple machines are behind a NAT firewall, which is very common these days.

  9. #9
    Programming Since 1978 silver trophybronze trophy felgall's Avatar
    Join Date
    Sep 2005
    Location
    Sydney, NSW, Australia
    Posts
    16,604
    Mentioned
    24 Post(s)
    Tagged
    1 Thread(s)
    Quote Originally Posted by Hammer65 View Post
    This problem pops up with online polls all the time. The only way to determine that a person has already voted is a cookie. If you do it by IP or any other system, you can run into a problem where multiple machines are behind a NAT firewall, which is very common these days.
    Also unless the visitor has a static IP address, the same address gets reallocated to different people all the time by their ISP.
    Stephen J Chapman

    javascriptexample.net, Book Reviews, follow me on Twitter
    HTML Help, CSS Help, JavaScript Help, PHP/mySQL Help, blog
    <input name="html5" type="text" required pattern="^$">

  10. #10
    . shoooo... silver trophy logic_earth's Avatar
    Join Date
    Oct 2005
    Location
    CA
    Posts
    9,013
    Mentioned
    8 Post(s)
    Tagged
    0 Thread(s)
    Lets go oever the uniqueness of that data you want to use.
    Code:
    $_SERVER['HTTP_ACCEPT']          == Contains the same thing across the same browser, only varies in some cases
    $_SERVER['HTTP_ACCEPT_CHARSET']  == basicly the same rarly different
    $_SERVER['HTTP_ACCEPT_ENCODING'] == same as above
    $_SERVER['HTTP_ACCEPT_LANGUAGE'] == can be different but will be the same for the same language
    $_SERVER['HTTP_HOST']            == same thought out every single browser accessing the site
    $_SERVER['REMOTE_ADDR']          == can be different not always, proxies, dialup could result in the same IP
    $_SERVER['REMOTE_HOST']          == not every IP has a hostname and some would have the same as they are from the same ISP
    Not very unique to me.

    Just use session cookies jeez how hard is that?
    Logic without the fatal effects.
    All code snippets are licensed under WTFPL.


  11. #11
    Theoretical Physics Student bronze trophy Jake Arkinstall's Avatar
    Join Date
    May 2006
    Location
    Lancaster University, UK
    Posts
    7,062
    Mentioned
    2 Post(s)
    Tagged
    0 Thread(s)
    dunno - it's probably because some people are that technologically-challenged that they beleive cookies are dangerous (probably because they read an article by some paranoid guy - refering to a thread earlier today, someone mentioned the guy's name).

    Alternatively, they might be hiding beind/using a proxy server.
    Jake Arkinstall
    "Sometimes you don't need to reinvent the wheel;
    Sometimes its enough to make that wheel more rounded"-Molona

  12. #12
    SitePoint Enthusiast traxxas's Avatar
    Join Date
    Jan 2007
    Location
    San Diego, CA
    Posts
    67
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by Hero Doug View Post
    I'm still putting my origional idea on the list as #4. A cookie can be downloaded, studies, and possibly used as a tool to hack into a site.

    The more information that has to be validated the harder it'll be to forge someone elses information.

    That's why I'm asking what other way's there are (using PHP) to get additional information about a user. Maybe there's a library or function I'm overlooking.
    Your solution is to use a cookie. If you are paranoid about cookie theft ( very difficult ) and session hijacking just have a short session timeout and annoy the hell out of your users.

  13. #13
    Programming Team silver trophybronze trophy
    Mittineague's Avatar
    Join Date
    Jul 2005
    Location
    West Springfield, Massachusetts
    Posts
    16,457
    Mentioned
    160 Post(s)
    Tagged
    1 Thread(s)

    unique

    As long as it is for a single user session, you can add time() to the hash. Unless more than a single user has all the same variables and logs in at the same time, they will be unique. IMHO this should be workable. And if the info does get stolen it will be useless as time() is always changing.

  14. #14
    SitePoint Addict Hero Doug's Avatar
    Join Date
    Nov 2003
    Posts
    250
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    ok I suppose I'll reply to these in order.

    felgall -> good suggestion. I've researched how mod_auth works and I'll be using your idea in conjunction with other ideas. An extra layer of security is exactly what I'm looking for.

    Cholmon -> Yeah I’ve thought of that possibility (machines running behind a corporate router) Everything will be located in a database, and I’ll have to use client side functionality.

    Hammer65 -> Yeah, I've thought about the fact that some offices have the same software installed on all their machines and all use the same IP. It won't be too much of a problem though.

    logic_earth -> I didn't care much for the attitude but I'll reply anyways.

    $_SERVER['HTTP_ACCEPT'] == The same browser will supply the same value (for the most part), but there are many different browsers and many different devices (mobile for instance) meaning that this value alone can divide the users into at least 5 different groups. IE, Opera, Mozilla, Mobile (which has many different values itself), no value.

    With one variable I've already divided the users into five groups, and depending on the browser version, it may be further divided still.

    For instance, a user in this forum has

    Code:
    text/html, image/png, image/jpeg, image/gif, image/x-xbitmap, */*
    for his Opera 6 HTTP_ACCEPT value, while I have

    Code:
    text/html, application/xml;q=0.9, application/xhtml+xml, image/png, image/jpeg, image/gif, image/x-xbitmap, */*;q=0.1
    for Opera nine.

    While it's not much, I've already divided the users into around 10 (or more) level's or categorization with this one value.

    $_SERVER['HTTP_ACCEPT_CHARSET']
    $_SERVER['HTTP_ACCEPT_ENCODING'] = Your right, since their based on the browser they won't provide much weight.

    $_SERVER['HTTP_ACCEPT_LANGUAGE'] = I think this one will provide a fair amount of weight. Even in a melting pot like America there are millions upon millions of people who speak a language other then English. Even further, people in Britain may opt to use British English, Canadians may want to use Canadian English, and many Canadians will also have French installed. What's more is that millions of people speak more then one language, creating a fair number of combinations.

    $_SERVER['HTTP_HOST'] == My mistake, shouldn't be here.

    $_SERVER['REMOTE_ADDR'] == As noted above, not the most reliable identifier when coming from a corporation, but mod_auth provides a solution to this problem.

    Also, even though ISP's change IP's regularly, it should be stable enough to use for a single session which provides us with millions upon millions of levels of categorization.

    Also, dispite the fact that some people may have the same IP, when it's combined with the other information gathered it should be differentiated.

    $_SERVER['REMOTE_HOST'] == Some people will have it, some people won't. Even if there's only two possibilities, that doubles the possible combinations, and there are a lot more then two possibilities.

    $_SERVER['HTTP_USER_AGENT'] == I forgot to add this one. Adding the operating system, browser, browser id and other information into the mix will boost the possible combinations.
    [/code]

    I think the above variables can provide millions upon millions of possible combinations, but I know a select range of combinations will be used significantly more then others which is why I started this post; to see what other unique identifier's can be thrown into the mix.

    Quote Originally Posted by arkinstall
    dunno - it's probably because some people are that technologically-challenged that they beleive cookies are dangerous (probably because they read an article by some paranoid guy - refering to a thread earlier today, someone mentioned the guy's name).
    I'm anything but technically challenged, don't worry about that.

    The goal of this thread was to find other way's of identifying a user outside of using a cookie.

    traxxas -> No I'm not worried about cookie theft, as I said above, I just want to see what other way's there are to identify a user without using a cookie.

    Mittineague -> I like your idea, I like using time for stuff like this, and I've thought of a way to use.

    Anyways to the naysawers, here's the solution. It's very possible to identify and authenticate a user without using cookies.

    This is what I'm going to do (as it stands now) [thanks to those who provided useful input]:

    Get as much information about the users computer/connection as possible and store it in a centralized database. This is only moderately unique, but it's a good first step towards differentiating users. The other key benefit is that since the information is stored in a centralized location authentication from multiple servers will be a snap. It makes adding a new section to the site trivial.

    To overcome the problem of uniqueness I'll use PHP to emulate Apache's mod_auth module by reading and responding to the headers sent by the browser. It'll take a bit of work, but I'll have far greater control then simply using the supplied server variables. This also effectively mitigates the uniqueness problem.

    The one downside is that mod_auth sends the username and password in plane text format. Should someone intercept the username/password combination and send it in their own malicious header, they'll also need to be using the exact same computer/connection configuration as the user they stole the login details from in order to gain access.

    Using these two methods together will give me an extremely secure authentication system that's scalable beyond a shared hosting account, and there won't be a cookie used.

    Anyways, just to top if all off I'm going to record the login time, and combine that with the other unique identifiers gathered in some unthought-of of combination and hash it over and over to create a uniqueID that I can store in a cookie and use as yet another way to uniquely identify the user.

    Again, the purpose of this post wasn't to say cookies are dangerous (although they are if used foolishly), I just wanted to see what other way's there were to authenticate a user.
    Last edited by Hero Doug; Oct 12, 2007 at 05:20.

  15. #15
    SitePoint Zealot cholmon's Avatar
    Join Date
    Mar 2004
    Location
    SC
    Posts
    197
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by Hero Doug
    The one downside is that mod_auth sends the username and password in plane text format.
    Digest authentication is designed to avoid this weakness by having the browser send an MD5 hash of certain values (including the username & passwd) in the header of every request, as opposed to the raw user/pass. Check out the example 34.2 at http://www.php.net/features.http-auth
    Drew C King: PHP Developer
    <?= $short_tags++ ?>

  16. #16
    SitePoint Addict Hero Doug's Avatar
    Join Date
    Nov 2003
    Posts
    250
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Yeah I stumbled onto that not too long ago, it look's promising. The ony thing I'm a little unclear on (I haven't studied networking too much) is how much security it'll actually provide.

    If someone can intercept the header and grab the information then they already have everything they need. The browser will take the username and password and hash it before sending it, and the server is just waiting for a matching hash, so why not just send the hash?

    Like I said I haven't studied this very thoroughly so I would assume this has already been addressed.

  17. #17
    Theoretical Physics Student bronze trophy Jake Arkinstall's Avatar
    Join Date
    May 2006
    Location
    Lancaster University, UK
    Posts
    7,062
    Mentioned
    2 Post(s)
    Tagged
    0 Thread(s)
    if it's on a https:// protocol, it will hash it.
    Jake Arkinstall
    "Sometimes you don't need to reinvent the wheel;
    Sometimes its enough to make that wheel more rounded"-Molona

  18. #18
    SitePoint Zealot cholmon's Avatar
    Join Date
    Mar 2004
    Location
    SC
    Posts
    197
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by Hero Doug
    The browser will take the username and password and hash it before sending it, and the server is just waiting for a matching hash, so why not just send the hash?
    That man-in-the-middle, re-play attack is handled within the digest mechanism. Basically, when you first get authenticated, one of the values that is used to generate the hash before it gets sent to the server is a counter that starts at 0. Every request sent by the client increments that counter, and the server also keeps track of that counter. If someone sniffs your connection and tries to do a re-play attack by re-using a previous hash, the server will reject it. The counter value is always incrementing, thus the hash itself is different every time. It's a dull read, but check out RFC 2617 for all the nasty details.

    But like arkinstall said, if you ran this all over SSL (which is ideal), it'd be encrypted so nobody would be able to see the hash anyway.
    Drew C King: PHP Developer
    <?= $short_tags++ ?>

  19. #19
    Programming Since 1978 silver trophybronze trophy felgall's Avatar
    Join Date
    Sep 2005
    Location
    Sydney, NSW, Australia
    Posts
    16,604
    Mentioned
    24 Post(s)
    Tagged
    1 Thread(s)
    A session basically just stores a hashed value either in a session cookie or a query string and all the other info is stored on the server. While most web servers default to storing the session data in a text file in plain text format on the server you can always override the session call processing to encrypt the data or store it in a database or whatever level of server side security you consider appropriate. If you want to also secure the communications between the browser and server you use a certificate.
    Stephen J Chapman

    javascriptexample.net, Book Reviews, follow me on Twitter
    HTML Help, CSS Help, JavaScript Help, PHP/mySQL Help, blog
    <input name="html5" type="text" required pattern="^$">

  20. #20
    SitePoint Addict Hero Doug's Avatar
    Join Date
    Nov 2003
    Posts
    250
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    I like how the counter works it add's a bit of complexity but it's well worth it.

    Also I like using SSL and will probably do so in the end, but I want to take it one step at a time.

    And the one thing about overriding PHP sessions is that it's highly likely I'll use more then one server so I want to make sure everything it well syncronized, and that it's easy to do. I haven't looked into this solution so I can't comment on it.

    I'll just take it one step at a time though, so first I'll grab the information and work on reading/writing the headers.


Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •