PoC stealing Chrome's tab history

tl;dr; tab's history could be read from an evil page by probing each element on it

When navigating in the same tab, history object keeps adding each page to its stack. By performing some redirection and comparing previos/posterior lengths of that object, it is possible to determine whether or not the last page in the history has been visited. This PoC has been tested only in Chrome, but the method should serve for other browsers as well.

Let's suppose the following history state:

   | null | full_url_1 | full_url_2 | full_url_3 | attacker.com | // history.length == 5
   

Now, if we want to check which was the last visited url we need to open a new window referencing the current one (opener) and perform this algorithm with a dictionary of urls:

   1. N = opener.history.length // save initial history length (same SOP)
   2. opener.history.go(-1) // set the navigation pointer to "full_url_3"
   3. opener.location = test_url
   4. opener.location = "" // come back to same SOP
   5. N' = opener.history.length // new history length
   6. compare N and N'
   

If test_url corresponds to the last item in the history, the new history state will be:

   | null | full_url_1 | full_url_2 | full_url_3 | attacker.com | // history.length == 5
   

Because when redirecting to a same URL no new entry is add to the history. Otherwise, our state will be:

   | null | full_url_1 | full_url_2 | full_url_3 | test_url | attacker.com | // history.length == 6
   

Now do history.go(-2) (or -3) and keep iterating over the length of the history object in order to extract all the visited pages.

Open "incognito" window. Visit some random pages in the same tab, load this page in that tab and click.



Click to start