Background
One of our most popular Canarytokens is one we call the “Cloned-Site Token”. Essentially, we give you a tiny piece of JavaScript to add to your public webpage. If this JS is ever loaded on a server that doesn’t belong to you, it fires an alert. You can be alerted at an email address or webhook in the free version, or to your SIEM, slack channel or a bunch of other alternatives in the paid version.
The Cloned-Site Token is super useful at catching Phishers who duplicate your website as a pre-cursor to an actual phishing attack.
A notification that the website from http://thinkst.com was now running on http://fake-thinkst.com |
The Issue
Recently, a financial services customer was periodically getting alerts where the Cloned-Site domain matched their actual domain. This was unexpected, as the token explicitly should only trigger if the domains are different. In other words, the token for http://domain.com should only fire if the page is loaded at a different URL, but in this case the alert was firing even though the page was (supposedly) loaded at the legitimate URL http://domain.com.
Date: Thu Jun 20 2019 08:36:12 GMT+0000 (UTC)
Original Site: xxxxxxxx.com
Cloned Site: https://xxxxxxxx.com
Headers: Accept: image/webp,image/apng,image/*,*/*;q=0.8
Accept-Encoding: gzip, deflate
Accept-Language: en-GB,en-US;q=0.9,en;q=0.8
Connection: keep-alive
Forwarded: for=1.2.3.4
Save-Data: on
Scheme: http
User-Agent: Mozilla/5.0 (Linux; Android 7.0; VTR-L09) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.89 Mobile Safari/537.36
Via: 1.1 Chrome-Compression-Proxy
X-Forwarded-For: 1.2.3.4
- Rewriting slow pages
- Image replacement in the form of placeholders
- Disable scripts
- Stop loading of non-critical resources
Digging into it
For our customer we deployed a small server-side fix to make the token work again but were curious about these Chrome Lite pages. If Google is rewriting my site’s HTML, how are they not breaking SSL? Are they mitm’ing my site?
- Creating an enormously large index page. This should be rewritten right? Maybe?
- Massive unminified JS files
- Massive unminified CSS files
- Including links to content that was being blocked by Lite mode on other sites
It seems like there’s a flow in Chrome (Lite mode via close/open) that sets ‘document.domain‘ to the empty string “”, which is the reason the alert was triggering. (The observant reader would note that our token reported it was running at http://domain.com, that’s because we checked document.domain, and reported location.href. The bug means a disconnect between the two.)
So, if you were using Chrome, and your connectivity was bad enough, you’d drop to Lite pages mode, and then it would be possible for the document to be served from … Chrome on reload? So the document.domain would suddenly be “”.
Takeaway
This seems to be pretty unexpected behaviour and is interesting to us for two reasons:
-
- Any site making use of document.domain will have a bad day;
- We wouldn’t have known any of this was happening without a well-deployed Canarytoken!
This is the second time that Canarytokens deployed by users have found Chrome flirting with the creepy line. In 2018, Kelly Shortridge found Chrome reading files in her Documents folder:
I was wondering why my Canarytoken (a file folder) was triggering & discovered the culprit was chrome.exe. Turns out @googlechrome quietly began performing AV scans on Windows devices last fall. Wtf m8? This isn’t a system dir, either, it’s in \Documents\ pic.twitter.com/IQZPSVpkz7— Kelly Shortridge (@swagitda_) March 29, 2018
It’s the value of both Canaries and Canarytokens. Knowing when things go bump in the night.
Postscript
We pinged the Chrome team and got this reply:
Max, some of the lite pages are served locally by Chrome itself. Specifically, if Chrome has an offline version of the page available locally on the device, it will serve that page directly from cache. Since that page is not coming directly from origin, document.origin for those pages is not set.
2 comments On When document.domain is not equal to document.domain
document.domain appears to be deprecated. will you be modifying the wizard to use location.hostname instead?
When I saw the title of this article, I thought that it is unreal until I have checked it. As I am a programmer, I was so impressed about this ''domain'' error. Thanks for the explanation.