Hacker News new | past | comments | ask | show | jobs | submit login
Who am I: A mind reader (don't forget to view source) (tinsnail.neocities.org)
583 points by alloyed on June 5, 2014 | hide | past | web | favorite | 168 comments

Here's the same exploit disguised as a game, to make it less obvious that it's tricking the user into interacting with it: http://lcamtuf.coredump.cx/yahh/

Documentation of the game proof-of-concept: http://lcamtuf.blogspot.com/2013/05/some-harmless-old-fashio...

Cool. That is a neat trick/exploit never heard of it before.

Thx. for the links.

My first idea was clickjacking and social networks, but that probably is impossible.

That's really good, and a very informative forum post!

Reminds me of that hunter2 password thing. http://www.bash.org/?244321

Basically, the website doesn't know which of the squares are red, that depends on your browser state. By clicking the red squares, you're feeding it data.

The interesting observation I made out of this is that navigating there in an incognito window prevents any links from being considered as visited. That's good to know.

I could probably post a similar gizmo on HN with a results static page that says

Your interests are: (some subset of) Programming Science Technology Games <random other thing: Sports, TV, childcare, etc>

With literally no scripting, and everyone would find it "reasonably accurate" :D

> Your interests are: (some subset of) Programming Science Technology Games <random other thing: Sports, TV, childcare, etc>

Me being me, I clicked on random grey squares. I got exactly that.

There is a selection bias from the choice of URLs it provides.

Haha, tried it out and you are right.

I an a bit disappointed by the results anyway. Something like gender guess, sexual orientation, age range and political leaning would have been more impressive than the programming/movies graph.

That's because you probably clicked in roughly the same area. The squares are grouped on the page by interest.

Somebody else clicked all of the squares, and art was #1, with painting #3.

At first, I thought the OP had done exactly that!

Also successfully trolled. And I also thought something similar after trying to trick it a couple of times. Wasn't until I read the comments it all made sense - i was using work chrome profile none of my actual interests showed up just my professional ones.

Same thing here. I happen to be very interested in neuroscience as well, so when I read “don't forget to view source,” I assumed it would feature a bibliographic citation or something. doh…

That would be sort of a specialized version of the Forer effect: http://en.wikipedia.org/wiki/Forer_effect

fwiw, my results were very wrong

It uses a list of sites, the ones that are in your browser history are red squares. The results may be wrong for you if you cleared your browser history, or if you share your browser with someone else, or if you habitually visit sites you don't like.

Yes. Apparently I don't visit many programming websites, although that's mostly what I do, and I visit more gaming sites than anything. (I only play mario kart on my Wii occasionally.)

The selected sites are very biased towards things you can do in front of a computers.

So this nice "Who am I?" trick only shows an intersection of my interest with those of the author. e.g. its completely missing my 3 main hobbies, as sailing, sewing and vaping had not been on his list of selected sites.

I tried not to make the subjects biased, and many (most) of the interests are not those that I have.

However, I could only include high-level, reasonable common interests, as including more would cause there to be too many squares.

Heh. I clicked a few before I realized what was going on (looking at the status bar shows the link, which somewhat gives it away). You could prevent this by adding mouseover/out and onclick logic that removed the :href on hover and just colored itself red.

but i guess then it won't be red on hover.

But in that case, you can add CSS to make it red on hover.

This was really accurate to me. It seems they're using a:visited on several domains to create the "red square" effect.


And the only reason you have to click the red squares is to let it know which ones are red. If you try to look up the color of a square using GetComputedStyle, it always comes back gray. That was the resolution of privacy Bug 147777† (":visited support allows queries into global history").


What about if you make a screen capture from the page and use coordinates to read back the colours and correlate with the URLs? Seems a possibility based on http://stackoverflow.com/questions/9250505/how-to-upload-a-s....

html2canvas constructs its "screenshots" using information from the DOM, so that wouldn't gain you anything but unnecessary complexity.

Ah, OK, and other methods appear to produce blank images so presumably this route is purposefully locked down too. A java app or add-on would do it but they'd be a bit obvious for most users I'd think.

Here's a related Mozilla bug report from 2002 regarding the link visited issue: https://bugzilla.mozilla.org/show_bug.cgi?id=147777


I know that the `:visited` exploit is handled by the browsers so that you can't figure out by javascript what is going on...

but what if you used just CSS to figure it out? For instance, what if you generated the CSS which had a unique image it requested via the `background-image` property, stored the data on the server, then just requested the data from the server after the fact?

Do the browsers prohibit the usage of url-based css properties on CSS selectors with `:visited` or something? Does anyone have a link/reference to how the exploits were patched up?

Yes, they prohibit anything that might be used for this purpose.[0] So the CSS allowed for :visited selectors is limited to a small subset.

[0]: https://hacks.mozilla.org/2010/03/privacy-related-changes-co...

Great. Thanks for the link.

Could your draw the screen, then save that as a screenshot, and analyse the image?

Just what I was thinking. Can't you render the DOM to a canvas and then access the pixels in that?

Apparently not: https://developer.mozilla.org/en-US/docs/Web/HTML/Canvas/Dra...

> Visited-link styles aren't applied to links rendered in SVG images, so history information can't be retrieved, and native themes aren't rendered in SVG images, which makes it harder to determine the user's platform.

They thought of everything, :)

This just solved a huge problem I've been struggling with. This is beautiful - I don't actually want to know the information I've been trying to access, but it will make the experience better for the user. I now realize I don't HAVE to know - the browser knows, and that's all that matters. I just have to teach the browser what to do.

Original creator here. I'm super surprised to see this posted here.

I can answer any questions people have.

For those of us who don't know Javascript, I'll just ask in broad terms: What is it, how's it work, what's it do?

It's a neat little hack to predict your interests among various categories.

The hundreds of grey boxes that you see are actually links to sites belonging to different categories like programming, science etc. and the red ones are those that you have visited (based on your browser history). The basic idea here is of using the CSS selector a:visited to highlight visited links in red, and by clicking the red boxes the users themselves reveal the sites they have visited. The website then uses this information to draw a pretty pie chart showing which categories the user is interested in.

Apart from making it seem like a game, is there any reason why the user has to click the squares? Is there a way for the browser to report back which elements are currently red?

That used to be possible by reading the styling in JS, but that was considered a privacy bug, since any website could slurp information from your browser history. Therefore there was an overhaul of what kind of styling could be done based on history, and what could be read back about it in JS: https://blog.mozilla.org/security/2010/03/31/plugging-the-cs...

No. Or rather, there isn't supposed to be. About 8 years ago (see http://jeremiahgrossman.blogspot.com/2006/08/i-know-where-yo... for an early demonstration) it was possible. This was considered bad, because it could help malicious sites gain information about the browser history which might help with an attack.

The browser developers responded by minimizing what a ":visited" can do, so Javascript shouldn't be able to get direct, or indirect through CSS, access to that information.

I thought it was going going to be a psychological experiment in how patient I was in clicking the little boxes.

I'm not incognito mode but it didn't work for me.

Kinda weird.

If nothing else, I did get a good list of Programming and Engineering websites :D - http://pastebin.com/zrQ7EBnP

This is OT, trivial and a bit silly: How did you intend the json file? I tried with sublime but couldn't find anything to solve it. Didn't start an IDE for this.

There's several JSON formatter packages that can be installed via Package Control: cmd + shift + P, select "install package", then search for "json". I'm not sure which one I have installed, but doing cmd + shift + P in a proper context and typing "json" should give you an option for "Indent JSON" or similar.

Otherwise, there's always sites like http://pro.jsonlint.com/

I know, right? 10,000-ish ways to waste time at work.

Obvious question - how was the list of URLs compiled? Some are really specific like YouTube channels. On the other hand there are only 15 categories and there are probably a lot of people that would not get a single match or only something very generic like Wikipedia.

Creator here. The links were gathered by searching feedlys feed suggestions for different topics.

The coolest way would be cold, hard natural selection from Alexa top sites, possibly with weighting placed to relevant sites at the introduction of the dataset. Perhaps I will fork.

Your interests are: Google, Facebook, Youtube, Yahoo

Yeah - it might be even better to subtract the most common sites, so the results are more peculiar to you.

fivethirtyeight.com appears about a dozen times for me?

Links appear multiple times if they are relevant to multiple interests. Clicks are only counted once.

Couldn't one simply make a display:none on normal links and display:block on :visited, then stack them all on top each other with position:absolute and catch mouse events from each element via JS?

Browsers have a very limited set of properties that they allow in :visited rules, and display isn't one of them.

This is quite clever. By the way now I've got a nice list of blogs/websites that I should probably read for various topics.

That's what I was thinking too. Here's a prettified list of the sites used: https://gist.github.com/amjd/acc5e108bfb2f29f050c

Thanks so much. Been looking for an up to date blog roll like this for a while.

I was also thinking of using it as a bookmarks site. :)

If you open the console and run this script, it'll click every single square, giving a list of the most common types of sites in the array being used:

     for(i=0;i<$$('a').length;i++) {

I had to change it to start at i=1 to avoid clicking on the link to github and leaving the page

Ah, that makes sense, I wrote and ran the script before he open sourced it.

I remember reading about the old CSS history hack (an automated variation of the same theme), which worked until FF4 and IE9.

It's quite interesting to see how such a seemingly simple feature (a:visited) can completely override user privacy if not accounted for.

Hm. Do you really need interaction at all?

Can't you just :visited { margin/pos/whatever }, then probe the dom on that or related elems to extract the juice? Or have browser vendors thought of this?

This is a very old attack that has numerous security measures to prevent you from doing that now.

Interesting. Could this maybe be bypassed by looking at computed CSS values of an element?

Browsers lie in the computed CSS values. Regardless of whether you have visited the link or not, the computed style that JavaScript sees is always unvested.

I presumed as much. But if you can covertly jimmy the UI and parse the user's interaction, you can more or less get at the history like that anyway.

I don't see any secure way to handle this besides disallowing :visited styling entirely.

It's surprisingly hard to do. Since the allowed styling does not affect positioning in any way (you used to be able to change the font-weight, but not anymore) and the browser removes all :visited styling for client side html-image libraries such as html2canvas you need to generate a massive amount of clicks from the user or have them targeted only to visited elements such as this page does.

I'm having a hard time following here. What is "covertly jimmying a UI" and how would it allow you to exploit visited styles?

For a less "covert" example than I am sure the OP was thinking, you could have "click the red button to continue" sort of like this page does. :)

Wouldn't that also require a hundred same sized differently colored buttons, just like this site?

Not necessarily. What if the un-visited box was set to display:none? That would leave you with just the visited boxes showing.

Now make it even less obvious: create a false box with the proper :visited color. That's your bottom layer, your fallthrough if the user hasn't visited any of them. Now position all of the :visited boxes as exactly the same size and position over that bottom layer. Now, when the user clicks the button to continue, they're guaranteed to click either your fallthrough ("user has none of my sites") or one of those you are monitoring for.

The end result of all this is a page that says "Click the box to continue."

> Not necessarily. What if the un-visited box was set to display:none?

Then it would remain 'none' for the visited box too. Messing with 'display' is disabled in 'visited' to prevent this class of workarounds.

You could prompt the user through multiple pages of "questioning" under a similar premise of psychological analysis, or some other manipulation. This would reduce the number of buttons per page.

That's what I think he meant.

There's a new-ish hack recently out - "using requestAnimationFrame to time browser operations" http://arstechnica.com/security/2014/06/theyre-ba-ack-browse...

I remember there being a long string of attacks related to hooks of this kind, but as far as I know it is no longer a problem at all.

It's a good example of just how difficult browser security is.

The page itself can't tell what color the squares(links) are rendered as to the user. That's what the clicking is for. Mwaahaha...

Was on incognito and wondering why I didn't see any red squares...

That is, I am guessing, because there aren't any re-marketing cookies,history and other markers when you open the page in incognito

No, it was because incognito tabs don't have access to browser history.

This web-app's functionality is based entirely on browser history and has nothing to do with 're-marketing cookies' or other 'markers'.

Not to mention that the parent commenter clearly understood this fact.


At first I thought it would deduct information about me by analysing which squares I'd choose in what order and through other metrics like pacing.

"Could not determine interests. (Pssst, If you did not get any red squares, try visiting without being in Private or Incognito mode)"

Indeed I am unhackable.

I had a very similar idea a while back, except I was measuring onAnimationFrame times with a carefully crafted CSS stylesheet to determine which links were being painted as :visited automatically and completely hidden from the user.

Accuracy varied a lot between computers but in ideal circumstances (only browser running) it would have ~90% accuracy on each of 25 links I was testing against - the test took about 8 secs to run though.

Interestingly it never worked particularly well in chrome - chrome seemed to stop painting :visited elements after a certain amount which prevented it from working.

This is mind-blowing, mine was pretty accurate! I know I can view the source code, but is this/similar code available from GitHub or somewhere for us to use in our own weekend projects? (:

I hope to clean up the code and post it to GitHub tomorrow.

Thank you very much, that is very nice of you! ^^

For anyone interested in the source, I started hosting it on GitHub at https://github.com/Conlectus/WhoAmI.

do you plan to put the graph into the source anytime soon? i was curious at looking through the code.

I just added the graph to the source.

In Firefox, you can go to about:config and set layout.css_visited_links_enabled to 'false'. This page, and others that hack the visited links styles, will no longer work.

Note that in Firefox only a few visual hacks will work nowadays. This means that sites can still change the local style of visited links to fit in with their colour schemes. BUT, you can't trawl someone's history by exploiting :visited any more.

And also note that this will remove all :visited styling, included the usual blue->purple. Just a heads up for people changing this variable because they think their privacy is being invaded.


I thought the a:visited exploit was addressed.

I spent an unfortunate chunk of time trying to auto-click all the red square via jquery in chrome console. After a lot of reading and experimenting, I can verify that the exploit is thoroughly addressed (so far), and I cannot achieve my goal because of it :(.

The most promising workaround would be to find a JS screenshot tool that doesn't rely on the DOM, and then run some client-side image analysis to get the index values of the red squares, and then go from there to click the things. Well played, exploit fixers, well played.

You could access the webcam and zoom/enhance the reflection in the eyes to get the screenshot.

Think I just found a way using canvas with a semi transparent element inside of it, then overlaying that on each square, grabbing the computed/resulting color of the canvas to decipher which block is what. S O O N

I tried doing this:


It appears as though Chrome (37-dev) will not receive any data from behind the canvas, while IE11 and FF(29) will allow me to see pixels behind the canvas, but only see the unvisited color.

I don't believe there is another method to receive the color of a pixel from a canvas except through getImageData(), but I could be wrong.

I don't think there actually is a way to take screenshots, w/o relying on the dom.

It was. The site can't know by itself what links are visited. It asks you to click on the visited (red) links, thereby giving it data.

That's why you have to click. Before the a:visited exploit was patched, a simple loop with GetComputedStyle would have sufficed. If you do that in a modern browser, all the squares come back color gray. The content script only gets to see the style attributes as they would be in the unvisited state.

The browser wont let the page get at the data, that is what was fixed, but you can still show visited differently to the user, and if you make only the visited visible and get the user to interact that information is revealed.

What's more interesting is that someone spun off Geocities and called it Neocities.

Here's the original discussion on HN: https://news.ycombinator.com/item?id=5957850

It was eerily accurate on me.

1. science 2. technology 3. programming

They could do the same game, but hard-code the results, and be right for 95% of the audience here :)

Actually, they don't seem to diverge much. I've tried randomly clicking on grey squares on different areas and it always gave me similar results (programming, gaming, technology, engineering).

I actually was going to come to the comments, assuming they had done that before remembering that I was supposed to view the source.

Hmm, I was: 1. technology 2. programming 3. history 4. politics 5. design 6. architecture

And it was dead-right.

same for me, though I barely read anything on history or politics

Pretty inaccurate for me. It game minimum value to books and writing, and i love them both. I just dont open enough links about them (i read the books! Not their sites!)

same with me, my first reaction is


1.Technology 2.Gaming 3.Programming

Did you ever heard of cold reading?

hey thanks, i just googled it.

I knew something about it (like reading expression or something, from watching 'the mentalist'), but i did not know what it was called.

but CMIIW the technique used in the linked app is categorized as 'hot reading' right? because it somewhat gather information from our "browsing history". Somewhat same technique used by google for user 'profiling' maybe?

just a little bit of assumption.

The hot reading is researching information on you directly which is less relevant in this case as you don't leave implicit traces of "I love reading Konan Doyle" in your researchable browser history. You may have visited some Konan Doyle sites but you can still do it for other reasons than actually liking his books so any such attempt will include a lot of guesswork.

No, it's exactly cold reading, because it tries everything and encourages and watches your reaction (with javascript) to determine which things it was throwing against the wall were relevant to you. It's an ePsychic™:)

guess I sure do love them movies from torrents.

1. technology

2. movies

3. books

4. programming

5. science

6. politics

7. gaming

I swear to god I only clicked one link to Salon and I didn't even mean it. STOP JUDGING ME

Hahaha. I was giving it the benefit of the doubt before viewing source, and so I was wondering what happens when I push gray instead of red. :P That is probably why I got some weird interests in my results.

On my second try, determined to find out how it works, I drew a random smiley shape in grey box area. Painting was added to the list! Was so disappointed to find out it was a coincidence.

From the number of squares, I thought it might end up doing something even more 'clever' i.e. generate a square for each of the most recent n URLs from feeds of m news sites, then analyse, for example, words in headlines of those articles to determine what I'm interested in. Lots of potential for data analysis once you have someone's browser history.

Once again, creator here.

I just pushed an update that added more topics and graphs. I have had reported problems after the update. Can anyone confirm?

I was in Fx Private Browsing. I spent about fifteen minutes trying to figure out why I had no red square!

Doesn't work for me because I disabled :visited last time this sort of thing got discussed. :V

This is really clever. One interesting use for this would be to target ads at people who visit certain sites, or to customize your site's landing page to direct visitors toward areas they might be interested in.

I made an automated version, check it out here: http://projects.milankragujevic.com/jspy/

I remember few years ago this concept was demonstrated as an way to get user website history from the browser. This is big privacy hole. And sadly nothing changed. Which is sad.

In a way it is, but only really through tricks like this one. Browsers can no longer access the properties of :visited, but they can affect how visited links are displayed.

I get the same three red boxes in Chrome every time, and none in Firefox or Safari. I get three categories at the end, with no links or anything. What am I doing wrong?

It shows you squares for a bunch of websites. Those you visited before in that browser are red. By clicking them, you tell the site that they are red, thus that you visited them. Each site belongs to a category and thus it comes to its conclusion.

What do you mean? These red boxes are links to sites you've visited in the past, they aren't showing up in Firefox or Safari because you don't have any of those sites in your browser history.

This works by showing you a grid, each box represents a website, to which the creator has ascribed a category(tech/gaming/etc...)

If you've visited one of those sites the box will appear red, and by clicking on the box you let the site know that it is something you've visited in the past and therefore likely one of your interests.

There are much more effective tricks to use in production. You can leak user's FB token for some huge client, and you get his email/name/bio.

This was exactly backwards for me... maybe I read it upside down? I jest, but the concept is cool, just needs to be refined I'm sure.

Should explain itself better. All I get is a bunch of grey boxes (no red ones) and if I click done I get "Your interests are:"

Thanks for the suggestion! I made it so that it explains itself if you don't click any red boxes.

Oh also it's easy to check if you're logged in on Service1 using CSP. No user interaction, same results

No red squares here. Am I doing it wrong?

I don't have any either. I think it's because I've turned off internet history on Firefox.

Yep. I took me a few minutes to figure out why it wasn't working for me...

You likely have layout.css.visited_links_enabled (or the equivalent boolean on your browser) set to false.

Maybe this link just saved my life!!! The clue for the clueless is in their forgotten yesterday.

Improvement: You can make the gray boxes light enough (same as bg) so only Red are visible.

the trick with a:visited is really awesome :D

see on github: https://github.com/Conlectus/WhoAmI/blob/master/css/main.css

Some people are just too genius or protective of their privacy to enjoy this! :)

Results are good except that I have no gaming sites in my history actually

It's a shame I had only 4 red blocks. I should diversify :)

Fun experiment !

Can we use this for filtering hacker news articles?

can someone post a screenshot of what happens once you click all the red boxes? I have too many of them and dont want to do it ...

Haha, should have been pr0n sites :P

How are the categories obtained?

It didn't work for me.

funny, perfect result!! and the concept is so simple, well done!

Nothing was red for me

You cleared your browser history recently?

I am <blank>???

Wao, reading my browser history while I am playing a stupid game. Elegant. :)

Not quite. See discussion above. You gave it your history by clicking the red dots and not clicking the others.

This is pure genius.

I had opened link in Private (incognito) window. #fail

Hmm, clever.

piratebay is not movies


I just read the source code, uses caches.

This can be done without any user interaction (and most likely has done to you without you knowing it). Check this link for 101: https://stackoverflow.com/questions/1584850/is-it-possible-t...

Here is a white paper of another exploit without user interaction, which is still working on most browsers. It's called "Pixel-perfect timing attack".


The related bug on the Chrome tracker was closed with a "won't fix".

Note that is from 5 years ago. Modern browsers have put up defenses. Others have linked to sources throughout the thread/

Guidelines | FAQ | Support | API | Security | Lists | Bookmarklet | Legal | Apply to YC | Contact