September 25, 2015

Uncovering a super-persistent tracking cookie

This is why we can't have nice things in web development.

Uncovering a super-persistent tracking cookie

Like anything in web development, developers have a choice to make: do they use technology in a responsible, law-abiding manner or not? Do they write code and systems that are helpful and beneficial to the visitor or not? As much as I would like to see everyone using their talents for good, I know that does not happen. Who do you think black-hat hackers are and what they do?

One of the many privacy invading tricks not-so-nice developers use are supercookies, evercookies, and similar techniques. These often make use of the “standard” HTTP cookies but are enhanced using Adobe Flash or HTML5 storage methods to make them harder to delete. These tricks raise legitimate and possibly serious security and privacy concerns, for they easily permit long-term tracking.

However, as I recently found, one does not need Flash or Evercookie techniques to create a super-persistent tracking cookie. All one needs is a bit of PHP, JavaScript, and server-side rerouting.

Note: I am not endorsing or recommending any of the following techniques. Persistent tracking of this nature is very questionable and concerning, and upon finding this I was rather disturbed it was going on. Please do not replicate any of the techniques I am going to detail. Always use responsible and law-abiding analytical methods with the visitor’s consent.

Byet Internet Services is, upon first glance, a rather sketchy-looking website host. However, they are known as one of the very few hosts offering completely free hosting.

Well, mostly free. There are a few catches, such as having to maintain a certain level of activity in order to keep your account and subdomain active. I once had a domain myself but accidentally let it expire from inactivity. Overall, the requirements for the hosting is nothing really obtrusive, that is, until 8 August when a buddy who uses the service often send me the following tweet:

Upon visiting his site, sure enough ?ckattempt=1 was tacked onto the URL. Upon opening the developer tools, I found a cookie from the site had been placed in my browser. I started by removing the query string and found it did not return. After confirming he had not changed anything lately and his account had not been compromised, I went to work reversing what was going on and figuring out why it was being done.

I quickly discovered server-side rerouting was at work. Upon removing the cookie and reloading the site, the page briefly flashed white and displayed a “Checking your browser” message before redirecting to the actual page with the query string added. Using timing and quick keyboard shortcuts, I was able to access the page source, which mumboking confirmed did not exist on the filesystem.

JavaScript was at play. Using three hardcoded strings confirmed to never change between loads and a symlinked JS implementation of AES encryption, the code generated a never-changing string that was used for the cookie’s value. The cookies itself was called __test , which I concluded was a sneaky way to throw people off and conceal its purpose and to possibly make visitors believe the site administrator was trying something out.

The actual source is minified, so I expanded it for legibility. (Gist)

Normally when “Checking your browser” messages are displayed, checks are being run to confirm your browser is compatible with the system. There are web apps that do these things (both legitimately and otherwise). By displaying such a message visitors are given assurance the page is loading and perhaps will work better because the web app has been customized to fit within their browser’s abilities and limitations. However, I had a feeling that was not what was going on here, as confirmed by the cookie’s hardcoded expiration date: 31-Dec-37 23:55:55.

Why would anyone use such an elaborate setup to generate a never-changing cookie with an expiration date 22 years from now? Easy: long-term visitor tracking. By using such a system across all their free domains, Byet would be able to gain substantial analytical data on all free domain visitors, even uniquely identify them (using server-side recorded values such as IP address, browser UA, and current time, among other possible values). Though I have no proof it is for tracking, the things I found next and later on helped solidify the theory.

This being discovered, I somehow suspected there was more at play. After reloading the page, to my surprise the query string had a value of 2, leading me to deduce ckattempt stands for “cookie attempt” with the value indicating how many times the tracking cookie has been tried to be set. I then deleted the cookie, causing the value to go back to 1. Deleting that, disabling JavaScript, reloading the page then reenabling JS set it back to 2, something I was able to successfully repeat multiple times (if I correctly recall the process used). If you did not already pick it up, the cookie was created every time JavaScript was activated, even if it already existed, creating a cat-and-mouse game if my buddy wanted to write code to delete the cookie automatically.

By this point, I was feeling very disgusted by the low actions being performed. Yet my gut feeling was If they have gone this far, they probably have gone even further. Up to this point, I had been examining the code only on the site index. I deleted the cookie and visited another page. Sure enough, the cookie came back, meaning server-side rerouting for the cookie-setting code was happening on all pages. I left the dev tools open and switched tabs to report my findings to mumboking. As I finished up, I switched back to the site just in time to see the cookie receive an update. I quickly looked to find what changed. A minute later, the cookie updated again. The only difference: time set. Byet has just gone even lower, I thought. They set the cookie every minute, meaning even if I did programmatically delete it, it would be recreated again.

Checking the forums showed this was new behavior starting Thursday evening or early Friday morning affecting everyone with free domains. It was implemented without warning and broke many sites, especially ones that used database connections (because apparently their code was still being run on the “browser check” page?). Naturally this upset a lot of developers, and without a proper response anywhere in sight, a lot of people were very, very upset, myself and mumboking included.

About a week and a half later I was thinking about this incident and decided to see if any developments have occurred. I started by checking mumboking’s site for any changes to the system. Though I found none except the removal of the checking browser message, in the process I did find that disabling JavaScript and cookies (or if I did not already have the cookie in my browser, simply disabling JavaScript) brought up another message stating JS was required to view the site.

I then returned to the forums to see if an announcement had finally been made. Sure enough one was, on the next Wednesday (a half week later), in my opinion too late to make an announcement explaining the sudden changes.

Hi All,Due to massive amounts of auto / bot /spam / application serving specific traffic causing performance degradation issues on free hosting services we have added new measures to reduce this.
You may have seen the new ‘Checking browser’ page, if so you would have also seen your page load faster than before after running this check.
The check is mandatory on free hosting, and may change over time, if you are using your free website for hosting a webpage, and this is causing issues contact us using the support channels in your vPanel.
If you are using your free hosting service for application hosting then we would recommend upgrading to premium hosting.
As always we are striving to offer the best ‘free web hosting’ experience, while dealing with the one in 100 that causes the problems for the majority.

I also found an unofficial response sent to an individual user on 9 August foreshadowing the official response:

The basic authentication was replaced with the current anti-bot secure option which relies on the fact that the visit needs to be from a real human.If you have seen any issues, please let us know and we will investigate. But this is currently mandatory on free service for security reasons.

To be perfectly honest, the reasons given sound like nonsense and an excuse. There could have been bot traffic that needed to be stopped, I do not know. However, placing a cookie and requiring JavaScript does not sound like a valid bot-deferring method to me. Most bots support cookies and JS, so this would only be effective against really old bots that are no longer of use and “real humans” with cookies and/or JS disabled or blocked via various means. (Side note: a user pointed out this same flawed reasoning as well). And did you catch the lines where it said the “check may change over time” and the check provides better server performance? It means they can revise the tracking system as needed to ensure they can continue collecting data, and last I checked placing a cookie did not increase server performance but can actually degrade client response (because cookies are sent through HTTP headers). I wonder if they realized both web developers and casual dabblers read this answer, as both are equally affected by it. Did they really think such an answer would make sense to people who creates websites and web applications for a reason?

In light of what I uncovered and the entire circumstance surrounding the ordeal, I maintain what I have detailed is a long-term visitor tracking system. All the practices and code used scream shady and suspicious with a rather lame (and late) excuse in an attempt to cover up the truth.

The bad news does not stop there. Because Byet wants to hide their tracking system, it means they also must break the law. In 2012, the EU passed a law nicknamed “The EU Cookie Law”. The law states all use of cookies, HTML5 Storage, and client storage of any sort on a site targeting EU citizens must be made known to the visitor. While the disclosure is only mandatory in the EU and sites/companies based in member countries, it affects everywhere else too because the Internet is worldwide and people from the EU can visit your site, even if is based in America. Therefore, while not required, it is almost necessary for US-hosted sites to display it in order to comply with the law. No where on any of the free hosting sites does Byet display the required message for this categorically “fairly intrusive” tracking cookie. The administrator of the site is left the responsibility to comply, but since they do not know the cookie’s purpose they cannot really display anything, likely causing the administrators to unknowingly break the law because of changes they cannot control nor were disclosed to them.

As a developer who aims to code responsibly and practice ethical behavior in all things, this super-persistent tracking cookie hurts me deeply. Such behavior is suspicious, questionable, privacy-invasive, and in my opinion plan wrong. The way Byet has engineered the system and handled the response is highly messed up. Such behavior is unacceptable and should not happen. Yet despite the wrongness of this whole thing, one question lingers: because the hosting is totally free of monetary payment, is there really much surprise we (visitors and admins) are trading privacy for payment? There is no such thing as a free lunch, so the lunch is paid for by various means, even if it is through nefarious means.