I saw a variation of this idea once with a space game. IIRC you control a ship and asteroids attack you. You shoot the asteroids by clicking on them.
The first trick: the asteroids are actually (in)visible depending on whether you had visited a specific website, same as here. If you clicked on an asteroid that's because you could see it, and now you've revealed that you've visited that website before.
Second trick: these asteroids don't actually hit you - they pass close by (close enough that you want to shoot them) but they don't actually aim at you (to keep you playing as long as possible).
Just like this site, you can put some “honeypot” ones that ARE real, and those can be aimed directly at the player, but also don’t trigger any sort of detection.
Presumably implemented in a browser using CSS :visited the state of which is inaccessible to web programs to protect user privacy. Toggle visibility of the asteroids in CSS and let the user unwittingly disclose which websites they've visited.
In Firefox it’s possible to disable behavior of visited links, thus mitigating this. Go to `about:config` and set `layout.css.visited_links_enabled` to true.
If you do this, beware this from the PoC when testing:
> Additionally, I included some fake squares to catch if visitors are trying to spoof their results.
Wait... if a random site can apply a style to a link to discern whether it's visited or not, why bother having the user click on them? Just render them somewhere outside the visual viewport and check what style gets applied to them? Or do browsers have countermeasures against this?
Sorry if this sounds kind of ignorant, but I do primarily backend stuff lol :)
The JS can't directly compute whether you have or haven't visited the link based on what it looks like. They actually used to (like 15+ years ago) but browser makers patched that REAL fast after some toy projects were able to reveal OUTRAGEOUS amounts of personal info just by getting someone to click a link.
Instead they have to have you the user do something to indicate which ones you can see and which ones you can't. That's why you HAVE to click on the squares. And if you click on white squares, it'll (wrongly) think you've visited sites you haven't. If you click on NONE of the squares, it'll think you haven't visited any of them, since it won't have any way to double check the info.
So that's why they can't "just render it outside the viewport." For sources, see the other comments by folks with good info.
> If you click on NONE of the squares, it'll think you haven't visited any of them, since it won't have any way to double check the info.
It's cleverer than that. There are two positive controls (squares that are always black) and one negative control (always white). If you don't click both positive controls, or if you click the negative control, the page will tell you that you've failed the CAPTCHA.
Has anyone seen this kind of attack in the wild or are we stuck with increasingly far-fetched blog post examples of someone finding out I've been to google.com?
> That's using the referrer header to detect if you clicked a link to their site from this domain. Totally different box of frogs altogether.
No, that's what they used to do until HN got updated to put rel="noreferrer" on the links specifically to stop that.
> Unless they're also doing some CSS stuff I haven't read about.
That's exactly what they're doing now. They have white-on-white text at the top of every page that turns red (i.e., becomes visible) if you've ever visited the HN submit page.
It’s high time browsers stop supporting :visited on cross-domain links by default.
No need to remove the feature completely, just not applying :visited on cross-domain links would fix privacy leak, while keeping most legit uses of :visited working fine.
It's been years that Google search result pages do not link directly to content, but goes through a google.com "redirect" url, so this use case could still work.
Agreed. Browsers should stop allowing a lot of things. In my opinion, they give way too much freedom to websites. That freedom can and should be taken away if it's abused.
Why can't we have situation where the CSS tells the browser what colours things should be etc, the browser does it, but the site cannot retrieve information about what colour the links are?
There's all kinds of things browsers do that no amount of coding will help me access because there's no public API for it. Why should this be any different?
This is the whole point of the link, even if the browser doesn't returns the correct information, there's still some ways to leak it through user action.
This is... great... A part of me loves it... but I agree with the author, there's significant possibility for data gathering if someone were able to find a way to convince people to go through these regularly -- boxes probably would raise a question mark to visitors (but worked perfectly fine as a POC).
:visited is per URL, and the PoC only checks the Twitter logged-out home page, so it's entirely possible that you haven't visited that recently enough to appear in your browser history.
This seems to me like it could be fully automated. What prevents me from rendering this into a canvas and then accessing the pixel colors from JavaScript?
I briefly touched on that in the explanation. The getComputedStyle function lies about the styling of links. I haven't looked into canvas based approaches but they're probably similar.
There are timing attacks that work automatically though. https://ndev.tk/visted/ works on Chrome.
The first trick: the asteroids are actually (in)visible depending on whether you had visited a specific website, same as here. If you clicked on an asteroid that's because you could see it, and now you've revealed that you've visited that website before.
Second trick: these asteroids don't actually hit you - they pass close by (close enough that you want to shoot them) but they don't actually aim at you (to keep you playing as long as possible).