9

Several years ago it was possible to use

a:visited {
   background: url('/log.php');
}

to figure out on what website user has been previously. But now it is restricted by browsers. Is there any other way to know which websites user have been recently?

curiousguy
  • 5,038
  • 3
  • 25
  • 27
Paul Podlipensky
  • 2,837
  • 4
  • 22
  • 25

2 Answers2

5

It is still possible. However, it is much harder to do unobtrusively now. See the following research paper for details of how to do it:

Please do not use this to spy on visitors to your web site without their consent. That has the potential to be a bad business move.

We've been through this before. The last time some web sites tried using CSS history sniffing, they eventually got caught. The fact that they were using history sniffing got into the news, and caught the attention of the FTC and many others. Lawsuits were filed, and investigations were opened. So I think we have solid evidence that if you history-sniff your visitors, you are asking for trouble. For more information on this, see the following sources:

D.W.
  • 98,860
  • 33
  • 271
  • 588
3

It's quite possible. The trick they've used to prevent this attack involves disabling CSS on the :visited selector. However, that doesn't stop the selector from still being there!

You can use JavaScript to iterate through a set of links, checking for the :visited selector on each. It's possible to do the check using cssRules, which should tell you which rules are being applied to a DOM element. Once you've found the visited ones, you can do an Ajax post back onto the site to store the results. There's a proof of concept of this trick, though there's no guarantee of it being correct and functional across all browsers.

Polynomial
  • 133,763
  • 43
  • 302
  • 380
  • I'm confused. That POC is from 2006 and is simply a POC of the no-longer-possible attack described in the question here (where you check the color of a link using `getComputedStyle` and from that infer whether it was matched by a `:visited` selector). It doesn't use `cssRules`. Nor does the `CSSRule` interface appear to offer any means of getting a list of all elements matching the rule. Am I getting something wrong, or is everything written here nonsense, as it seems to me? – Mark Amery Jun 01 '19 at 12:31
  • I wrote this 7 years ago, and I honestly have no idea. It does look like the PoC I linked doesn't use `cssRules` like I thought it did; it's possible it was changed after I linked it, but I could've just misunderstood. Anyway, if you'd like a newer approach, check out the [history stealing timing attack](https://antoinevastel.com/security/privacy/2017/04/09/history-stealing.html) which utilises animation timers to detect whether a CSS shadow was applied or not. – Polynomial Jun 03 '19 at 10:24
  • That approach too has been at least mitigated by reducing the precision of all timestamps that the browser reports to JavaScript. – Mark Amery Jul 06 '19 at 09:39