Moshe reports a lot of "Stolen Persistent Login session for user ..." watchdog messages at groups.d.o.

This error only occurs when PL sees a browser delivering a cookie it should not have. Generally this means an attack occurred. But if I suppose that the attack is less likely than a bug or other unexpected situation, I should look for an alternative explanation. I can think of one:

Suppose a user's browser is configured to prompt for cookies instead of just accepting them. When they log in with user/pass, they explicitly accept the TWO cookies (session and PL) they are given. When they later return and use the PL cookie, it will work, and PL will issue a *new* PL cookie, and *maybe the user chooses not to accept this one*, thus keeping the old one. Then, the *next* time the user tries to use the PL cookie, the error will be generated.

I asked the one user with an entry for this in the g.d.o logs about their situation.

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

markus_petrux’s picture

Status: Active » Fixed

I've been using PL for a while now, and I haven't seen this. g.d.o was running D5, so maybe something that only happens with that version.

Anyway, there's been no further feedback here, so I'm closing this issue. Feel free to reopen when more information is available. Otherwise, it is pretty difficult to guess without a method to reproduce the issue.

Status: Fixed » Closed (fixed)

Automatically closed -- issue fixed for 2 weeks with no activity.

ahoeben’s picture

Status: Closed (fixed) » Active

The module creates a false alarm when two or more requests for a page are made at the same time by a returning user. The first page request that gets handled by the module creates a new token. However, the second (and following) requests have already been made with the previous token, so when handling the second request the security warning is issued and the user is logged out of all sessions.

I can think of at least two scenarios when a returning user would make two or more requests at the same time (with the same old token):

  • If a browser-session is restored, multiple pages from the same site may be requested at the same time. This can happen eg after a browser crash, after returning from a private browsing session (Firefox), or simply when the user has a browser that stores the open pages/tabs when the browser is closed (eg Opera).
  • Browser-integrated RSS feed reading. Eg Opera Mail shares its cookies with Opera, and when a user is subscribed to more than a single RSS feed on the site, it may make multiple requests at the same time (ie: before the first is processed)

Neither scenario is all too uncommon.

The only solution I can think of for these scenarios is to accept the previous token for up to a couple of seconds after a new token is created. But that would take some work to implement, and it would probably introduce a security loophole of up to a couple of seconds.

sbogner@insightcp.com’s picture

I got this warning today, and after checking the logs I'm fairly confident that no one else logged in as me. What I did do, earlier, is access my site via my laptop on a docking station with a hard-wired connection and IP address 'A' (for example). While that browser session was still live, I undocked, which changed my IP address to 'B'. Everything worked fine. The next day, I come back to my laptop in the docking station with IP address 'A' and it gives me this security warning when I access the site.

protoplasm’s picture

getting same messages occasionally

plan9’s picture

I also have this problem and would like to disable the warning - it's far too anxiety inducing for regular users. Incidentally my browser is set to 'accept all cookies'. I'm using 5.x-1.3

griever’s picture

I thought of a simple scenario when this false warning could happened.
When an user access the site using a browser (e.g Firefox), he is issued a new token.
When he access using another browser (e.g Google Chrome) which he has logged in before, he still have the old token, which is now invalid.

So if the user uses two browser, or two machine. this false warning could be raised.

I don't think to reset the token everytime is necessary and comfortable for end user, as many users use multiple browsers at a time.

gapple’s picture

That shouldn't be an issue, griever, as each computer and each browser on it will receive a different series cookie. Persistent login allows multiple computers/browsers to have their own login keys, not one key across all of them.

griever’s picture

@gapple: Oops sorry I'm wrong!
The problem is exactly as described by ahoeben. I've tried to implement the "Improved Persistent Login Best Practice" (the same as this module) in my system and got the same issue if i tried to open multiple tabs (The problem arise when I reopen those tabs)

griever’s picture

Maybe I should think of a different approach :( Maybe a fixed cookie, but it's less secured.

protoplasm’s picture

The problem is even happening on my localhost development server which is locked down and only I have access.

griever’s picture

Hi all, I've emailed the author of this scenario (Improved Persistent Login Best Practice) and here is his reply:

Griever,

You make an excellent point; that does seem to be a flaw in my plan. So far I'm not sure what to do about it. [B]The best I've come up with is to allow two requests from the same IP when they arrive very close together in time[/B]. Yes, IP addresses can be faked, but for exploit this workaround an attacker would need to know exactly when your browser is restarting in addition to being able to fake your IP address and knowing your PL cookie.

Of course, the truly paranoid would say the attacker could overcome needing to know when your browser will restart by actively causing it to crash at a selected time! That level of attack is probably beyond PL's ability to defeat.

Barry

I think I can use it in my system.

gapple’s picture

I don't think a window of a few seconds should be an issue: if an attacker has obtained your PL key set they can do a malicious request right away, with a better chance of success than waiting for the exact moment you log in with it or causing a browser crash (and not needing to fake your IP too, should that protection be added).

The issue I foresee would be detecting that intrusion later so that the series can be destroyed, which I think requires the opposite thinking: what if the user attempts to login while someone is using their compromised key - can we still notify them that their key was used by someone else? In this scenario the intruder is very unlikely to be trying a one-off malicious request with a spoofed IP, so the token reuse window shouldn't be an issue.

I would propose this process:

1. User logs in with PL cookie
If series & token are in PL table:
  2. PL token is placed in a cache table with a short expiry
  3. new token is given to client
  4. user is logged in
If series key is in PL table, but token is not:
  2. check for token in cache table
  If found:
    3. user is logged in.  No new token is provided since one was generated in the first request.
  If not found:
    3. Assume keys are stolen - series is destroyed

If the request times can be used for the token cache expiry, the timeout could be relatively short (e.g. 5 seconds). Otherwise, the timeout would have to be longer so that a long initial page request would not cause a later request to be outside the timeout due to session locking (e.g. a big page takes 10 seconds to generate, after which the second can start processing. The second page will start loading after the PL token cache entry expires at 5 seconds, and the second page will appear to use a stolen token).

I'm not sure if the cache table should be limited to one entry per user-series pair. It is possible that a later request using the new cookie could be made while earlier requests are still queued. If the later request were to jump the queue it would overwrite the prior cache entry and cause the initial requests to fail. I don't think this situation is likely, however.

plan9’s picture

Does anyone know of any alternatives offering similar functionality to this module?

plan9’s picture

I've just had an incident where the warning message got cached by Boost module and was being displayed on my home page to all anonymous visitors :(

Needless to say I have now commented out this message:

drupal_set_message(
t('<p><b>SECURITY ALERT!</b></p><p>You previously logged in to this site and checked the <em>Remember me</em> box.  At that time, this site stored a "login cookie" on your web browser that it uses to identify you each time you return.  However, the login cookie that your browser just provided is incorrect.  One possible cause of this error is that your web browser cookies have been stolen and used by someone else to impersonate you at this site.</p><p>As a precaution, we logged out all of your current sessions and deactivated all your remembered logins to this site.  You can log in again now.</p>'),
'error');
gapple’s picture

@plan9: that sounds like a valid, but separate issue. You should file a new issue in the Persistent Login queue for the conflict with Boost module.

tmsimont’s picture

I also received complaints of this message appearing on a client's site, and users were panicking.

All I did was change the message to not suggest that someone stole something from them... but I was thinking that another trigger of this might be the redirect that login tobaggon optionally triggers when a user tries to access a page they don't have permission to see...

Could you just make this message customizable on the settings page for this module?

plan9’s picture

@ahoeben you are correct about this being caused by feed - I just found this in my watchdog logs:

Date	   Thursday, 28 October, 2010 - 15:12
User	   Guest
Location    http://www.mysite.com/featured-events/feed
Referrer	
Message	    Stolen Persistent Login session for user Administrator detected.
Severity 	    notice
Hostname  80.125.50.20

Is their a workaround / patch for this?
Is this fixed in 6.x branch?

gapple’s picture

Version: master » 6.x-1.x-dev
Assigned: Unassigned » gapple
Status: Active » Needs review
FileSize
7.28 KB

Here is my first scratch at a solution.
This patch has not been tested! I mean at all, other than it applies to current dev and my editor doesn't complain of any syntax errors. I would appreciate feedback on the approach most of all, as I'm not sure if any additional modifications are necessary.

A new table is added to the database, basically a copy of the main table except that the `expires` columns are not equivalent and there is an additional `ip` column for the IP address of the client who invalidated the token.
An update hook will add this table to older installs.
Expired entries are deleted from the table on cron.

Entries are added to the cache table through the token invalidation function whenever the 'used' operation is specified. I've set the default validity time to 30 seconds, specified in a constant, though I'm hoping it can be reduced to a lower value.

The conditional to check token validity is modified to additionally check for any recent entries in the cache. The actual operation is performed by a helper function which caches the result, since it needs to be checked twice on each load. The IP addresses must match between requests: only the IP that originally invalidated the token can be authenticated again through the cache.
The token is only invalidated or a new cookie sent if the request is not valid through a cache entry so that a new token is not generated multiple times, or the cookie sent needlessly.

plan9’s picture

I would like to test this patch but I'm using 5.x-1.3

gapple’s picture

I've found another way to trigger the alert in this manner:

1. Load a (long-running) page, but cancel the request quickly
2. Reload the page

It seems that this will cause the token to be invalidated on the first request, but since the browser cancelled it won't receive the response with the updated cookie value. The next request repeats with the original, now invalid, token value and causes the security alert.

gapple’s picture

@plan9
Best practice is to test code in the newest release (6.x) and backport once completed, especially since only 8% of users have a 5.x version. After a quick look the code in both versions seems pretty close, so you could port the patch fairly easily if you would like, but the focus should be on getting a 6.x patch ready to commit.
(and I hope you've heard it many times already, that you really should be upgrading with 7.x on the horizon)

plan9’s picture

@gapple, unfortunately I don't have a 6.x install to test on. I'm stuck in the 5.x 8% until at least next spring.
I've found an alternative module: http://drupal.org/project/remember_me which I'm now testing.

YK85’s picture

subscribing

maddentim’s picture

I am seeing this consistently lately on a couple of sites. One is a week old site underdevelopment. Hardly one that anyone would have any interest in hacking into. I am fairly certain that no one has stolen my cookies. Definitely going hack the message content for the warning as #17 suggests.

Wondering if what is causing my warnings comes from using Chrome's password syncing function...

gapple’s picture

@maddentim
I don't use Chrome myself, but password syncing shouldn't duplicate the persistent login cookies which would result in the security warning.
It may be helpful if you turn on the logging for token invalidation in order to get more info on what's occurring. It currently requires a simple code change, or I have a patch in another issue to allow toggling it from the module settings (#848774: Enable login invalidation logging on administration page).

The two instances that are known to force this error currently are
1. Simultaneous page loading, either via multiple tabs or by separate programs that share cookies.
2. If an initial page request is stopped before the page data and the new cookie are sent to the client.
In each case the second request sends the same cookies as the first, but the original cookie was invalidated and removed during the first request.

maddentim’s picture

@gapple
thanks for the info. I will see about the logging. Might be that simultaneous page load. Definitely use multiple tabs often and with the same site. Especially with ones I am building...

maddentim’s picture

Hello, just following up on this one. Here is a patch with softened message to the end user. It seems to be that since the only thing we know for sure when this message is displayed is that we can trust the cookie any longer that we should leave it at that.

gapple’s picture

@maddentim
I like the shortened message, and having it be less alarming to the user.

I think it would be helpful for the message to link to a page with more information on how the login system works, and details on what caused the error. Some users may still be very concerned, and I would want to have sufficient information available to them to either allay their worries or allow them to research and deal with an actual threat.
For now, it could also list the know problems with the system for both the user's and site maintainers benefit.

maddentim’s picture

@gapple
A page with more information sounds like a good idea.

As a site builder, one of my constant concerns is making sure that I control the user's experience. In fact, the whole login / authentication process is one of the thorns in my side. This is one the reasons that I really appreciate this remember me module. Having the ability for users to return to a site and not have to remember what password they used is huge. While they can get a new one easily through the request new process, it still just gets in the way of the experience. In many of the situations I encounter, I need to authenticate users where the security of the data involved is not particularly sensitive and the authentication is really needed just to deliver the right content to them. It is a shame that efforts like OpenID haven't really panned out as hoped.

The last thing I want is my users, who are generally not technically adapt, to fear the remember me option. I have been meaning to ask some of my more seasoned / trusted client administrators to ask if they have ever run into it. I am hoping they haven't and that my own developer side actions are causing me to see it from time to time.

maddentim’s picture

@gapple
One of the things that I will often do when build a site is migrate databases back and forth between my dev / staging / production environments. i.e. I will back up the db in production and restore it into my dev. If I had 'remembered me' on production, and the accessed the site on my dev (with a different url / IP), would this scenario trigger the security warning? If this is the case, I would ease my concerns about it as I am the only one who would encounter these things. And if so, maybe I could have BAM exclude the persistent login data from the backup...

gapple’s picture

Moving tokens from one site instance to another can definitely cause issues. You should not move PL pairs through development -> staging -> production, and while not harmful you should avoid moving them from production to development.

When your series:token pairs are moved from production to dev, your browser's cookies for the dev site (if present) will have a different series key than any from production. When first accessing the dev site PL won't find your provided series in the database, so it will just ignore your cookie and you will need to log in. Using the remember me option will then cause a completely new series to be created on the dev site.

If you then move the same data back to production (through staging), you may overwrite more recent user tokens. If a user then visits the site again, PL will compare the user's more recent token key to the older key in the database for the series; this mismatch will cause the security warning.
If there were any new pairs created in production after you copied them to your dev site, they will be removed and the user will be forced to log in again (though they won't receive a security warning).

You'll have to check your site logs or enable PL's token logging to check if user's are encountering the security warning on the production server.
----

On one of my sites, I had to restore a recent backup while a user was online. Their Drupal session was destroyed in the restore and the backup contained the PL token key from before they logged in and a new one was issued. When they visited a new page after the restore completed, PL attempted to log the user in but a token mismatch was detected and they received the security warning.

maddentim’s picture

Ok, thanks for the info. I'll look into excluding the PL tokens from BAM backups. I'd rather they had to log back in. besides, this user is usually me :)

smokris’s picture

Re-rolled patch from #19 to apply to 6.x-1.x.

cgmonroe’s picture

Re: Scary default messages...

They can now be themed with the patch from #1203056: PL Bootstrap state notification

gapple’s picture

Title: Possible false security warning » Security warning triggered by simultaneous requests
Version: 6.x-1.x-dev » 7.x-1.x-dev
Status: Needs review » Needs work

Bumping version; needs 7-x.1.x patch

gapple’s picture

Issue summary: View changes

In the process of porting to 8.x, I found there may be another way to handle this issue, without requiring another database table. I'm not sure how much of a change it will require to implement in D7 though.

The token handling is split between processing the incoming request (where validation occurs), and altering the response (where updating / deleting occurs). If the main process of the the first request takes a large amount of time, the token is not yet invalidated so the second request will still succeed. When both requests end, they will each attempt to update the database and send a cookie to the user, only the last of which will be stored both in the database and by the user.

ron_s’s picture

I've added a patch that at least allows the security alert to be customized, regardless of the approach taken.

Please review, thanks: https://www.drupal.org/project/persistent_login/issues/3135961