0

This question is similar to Hashing cookie-values & preventing cookie-stealing however, it is significantly different as I am interested in preventing (internal) subscription fraud, rather than an attack on the user's terminal from a malicious third party.


I have been using a simple local cookie to save my paid-subscriber site's user's user id. This prevents them from becoming annoyed by constant log-in requests. Nothing out-of-the-ordinary here.

My concern is that it is too simple and can too easily be hacked by cutting and pasting the PC's local cookie file.

If I were to track down my local cookie file on my PC, which is easy enough, I can copy it to a text reader and search until I find the info related to my site:

GA1.2.662049077.1549644533U8EMOÔ¬AÔ¡Aexample.com__atuvc/1%7C5~8GPRÄâ’
¬AÄ…;N¡A.example.com__cfduid/d1240692ee84f4c8c756cee833d313a841558986
714ì±3µ”`ËoÙ_8O[]Ñcˇ¡Aƒ¡Awww.mysite.commy_cookie/7www.example.com8O^~
áA¢π¡Awww.GA1.2.662049077.1549644533U8EMOÔ¬AÔ¡Aexample.com__atuvc/34
GA1.2.662049077.1549644533U8EMOÔ¬AÔ¡Aexample.com__atuvc/

And there it is: www.mysite.commy_cookie/7

It wouldn't take an overly talented analyst to figure out that this is a cookie which stores the user id for user # 7. If badhacker325 wanted perpetual access, badhacker325 could paste www.mysite.commy_cookie/7 into the local cookie file and have perpetual, free access.

As coders and bakers of cookies, what tools do we have to prevent this kind of freeloading attack?

It might be germane to know that I am working in php; though the scope here goes beyond coding language, imo.


Not being the lazy sort, I have tried to work this out. I have solved for some scenarios, but I'm stuck on one component which I will identify below (mostly to maintain the suspense). Here are my attempts so far:

I have – instead of storing the simple user id 7 – created an array of:

user_id
cookie_creation_time
user_ip
salt

I then imploded that to a delimited string, hashed it to unrecognizable bits and stored it. Now we get a cookie like this:

www.mysite.commy_cookie/d1240692ee84f4c8c756c
ee833d313a841558986771www.example.com8O^~¬3†¢

This, however, still does not stop a user from idiot-savant copying the hash to their local cookies file and gaining access to my site like nothing was ever wrong.

What it does do correctly:

When reading back the IP, the script can discover that the users location is different from the location at which the cookie was set. This is a fail state, and the user is requested to re-enter their password.

This solves for space, but not time. (I'm not Einstein yet.)

My next thoughts were to use the creation_time value to test against a server value, and if that fails, to have the user re-enter their password. However, this seems to defeat the purpose of the expires parametre of php's setcookie.


I suspect that I am overthinking this — or perhaps have misinterpreted some aspect of cookie usage altogether.

Does anybody have any thoughts? How can we prevent a high-jacking of the user's local cookie file to exploit accepted cookie use?

7
  • 2
    You need a design that doesn't rely on the end users maintaining secrets from themselves ... You need to not encode the entire authentication logic in something you then give users. The fix is not a better cookie, but a better authentication logic on your server.
    – schroeder
    Nov 25 '19 at 15:32
  • Down votes? Why? This is plainly well thought out, and has attracted two helpful answers (one upvoted three times) and even a decent comment in under an hour. Does this not add to the community? While I read and research these answer, please let me know why this deserves down-voting.
    – Parapluie
    Nov 25 '19 at 17:24
  • There are canned reasons for downvotes. Maybe people were thinking about those things.
    – schroeder
    Nov 25 '19 at 18:14
  • 1
    If I were to downvote it, it would be because the identification scheme relies on parts of the user's ID (as it's stored in the server, and as it's probably non-trivial to change that ID) inside of client-side data... and the fact that libraries that provide identification scheme each typically store a very high entropy, (cryptographically securely) randomly generated nonce in the cookies, rather than an (encoded) ID. -- The question shows obvious thought, but doesn't show investigation into prior research in the area.
    – Ghedipunk
    Nov 25 '19 at 18:27
  • @Ghedipunk and schroeder Thank you both. I suppose that you are correct. I did do the research in fact, but I didn't have the lexicon to describe my dead ends above (Anders and mti2935's answers, in fact, helped with that). I've always tried to be a patient and respectful coach with new posters on SO. I guess I'm a bit naïve to expect that for myself, eh wot? C'est la vie.
    – Parapluie
    Nov 25 '19 at 18:58
6

As I understand your question, you are storing the user ID in a cookie. The server then blindly trust this value when the client sends back a user ID.

That design is vulnerable, and trivial to hack. An attacker doesn't even need to copy a cookie, just set one to an arbitrary number and bam, you are logged in as that user. Your suggested fixes does not solve the problem. Using an array might obfuscate it a little, but nothing more. Checking the IP doesn't help if the attacker is on the same network, e.g. a different computer on the same workplace. It also brakes the site for many mobile users, who may have different IP:s as they switch between cell phone towers.

The root problem here is that you trust the client. To fix this problem, your server must stop trusting any information the client provides it with. There are two main ways to accomplish this:

  • Use sessions. The cookie only contains a random unguessable ID, then information like what user is associated with that ID is stored on your server.
  • Use signed cookies. There are existing implementations for this, the most popular being JWT. You should not try to come up with your own implementation!

Note that none of these protect you against an attacker with access to the victims computer simply stealing the cookie. But that is not an attack you really can protect from (unless you want to have constant password re-entry).

2
  • 1
    This has definitely steered me in the correct direction. Mostly, I needed to learn the terminology. Btw, I'm already using sessions and auth, but I couldn't figure out how to integrate the persistent cookie into the design. You've giving me the path to follow. I'll do my research. Thanks again.
    – Parapluie
    Nov 25 '19 at 18:07
  • To address the lost cookie vulnerability Anders mentions: If an attacker steals a victim's cookie and distributes it, you'll see strange traffic patterns from the logged in user, and can force a password reset or cancel the account. In general, users don't share credentials/cookies for paid sites with strangers, since it tends to backfire (account details like payment settings being changed, bookmarks and recommendations not working effectively, account being closed, etc.) The more sophisticated content thieves will create an unauthorized mirror instead.
    – Brian
    Dec 3 '19 at 22:42
1

Token binding and Channel-bound cookies are one solution to this problem. This is where cookies and other bearer tokens are bound to the TLS channel, so that these tokens can not easily be stolen and used in another browser. For more info, see http://www.browserauth.net/.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.