The Phantom Menace : Headless Browsers & Cybercrime


1. Headless browsers

Headless browsers are browsers without GUI. They are mainly used for test automation and web scraping, but we will see that they can be very useful and convenient when used for cybercrime activities. In this article, we will mainly be considering PhantomJS and CasperJS. You can find an exhaustive list of headless browsers here :

2. Headless browsers and banking trojans

Banking trojans never disappeared. From 2007 to 2014, they were the main type of malwares because of their level of sophistication and their Man-in-the-Browser features allowing them to perform webinjects and form grabbing in order to steal credientials while bypassing most protections. They didn't really fall out of fashion but got replaced by ransomwares, easier to program, maintain and more profitable overall. One interesting feature of banking trojans is their ability to use Automatic Transfer Systems. These were frist seen in 2012 and were designed to conduct automated wire transfers without the victim noticing anything. It basically consists in Javascript scripts injected into web pages by a banking trojan via Man-in-the-Browser that can fill or modify forms and send Ajax requests to, for example, change the legitimate recipient and amount of a transaction on-the-fly in order to transfer money to mule accounts.

To mitigate such attacks, banks started deploying behavioral analysis algorithms and hackers stopped using them, prefering conducting transfers using VNC (or equivalent) backconnect features, more time consuming but undetected by behavioral analysis. Headless browsers allow an attacker to automate wire transfer, not in the same way as an ATS would since it doesn't use the fact that the victim is logged in and hijack an operation, but would be a far quicker and convenient way for an attacker to make fraudulent transactions or transfers than using backconnects.

So, provided that an attacker stole someone's credentials with a MitB trojan, he can easily automate logins and further operations on most websites. However, bank login pages are a bit more complicated and use virtual keyboards, so how can an attacker manage to log into the victim's online bank account in this case ? Well, I looked into the login pages of french main banks during my internship and came across some worrying implementations : some virtual keyboards found on bank login pages are so poorly implemented they don't mitigate anything except keyloggers from the 90s. Look at this one for example :

Seems solid right ? Well, if the keyboard is decently implemented it is supposed to be designed so that it is impossible to retrieve what numbers are in each case by looking at the html source or the POST requests. But on this one (and others), the numbers are simple text nodes, which means that you can read them with CasperJS and use click() to simulate a legitimate user's behavior and log into the account. Another example, where the numbers can be retrieved by reading the data-passkey or src attributes in the ⟨li⟩ and ⟨img⟩ tags :

Both of those pages are also vulnerable to form grabbing since they send the actual password through POST instead of the positions of the clicks in the virutal keyboard as it should be. This is very sad and worrying that we still see this kind of mistakes, especially on online banking websites.

Even if the keyboard is secured, it will still be possible to use CasperJS to automate logins. One scenario could be to save images that are displaying the numbers in the pad and compare them with images we know the number they contain, as explained here :

Another interesting fact is that ATS can be easily detected by anti Man-in-the-Browser Javascript protections that scan the DOM and inspect Javascript objects in memory and send the result to a server to spot if anything was injected or modified. I developed such a protection based on this talk at BlackHat US15 during my internship and could easily bypass it with CasperJS using the following instructions :

casper.on('page.initialized', function() 
{		this.evaluate(function() {
			delete window.callPhantom;
			delete window.ClientUtils;
			delete window.create;

You can check it by yourself with the code below, based on the Sean Park's implementation, which scans the Javascript objects in memory and displays the name of the functions. This is due to the fact that, even though CasperJS evaluate() function executes Javascript in the remote web page context, scripts in this remote context are not able to see objects from CasperJS except the global ones registered by PhantomJS : window.callPhantom(), window.ClientUtils()... This is why we delete their references when we load the page.

3. DDoS attacks using headless browsers

If we haven't seen a banking trojan installing a headless browser to perform malicious transfers yet, they have been actually used multiple times to do DDoS attacks in the past two years. In the last few years, anti-DDoS companies have come up with solutions that can mitigate DDoS attacks by implementing challenges that classic "dumb" bots can't pass. You can find some of these challenges in this document ("Headless Browsers and DDoS - Attacks Become More Sophisticated" part). Redirect challenge, Javascript challenge, cookie challenge and the mouse challenge can all be easily bypassed by a headless browser like CasperJS, this is why hackers started using it.

In this article, an anti-DDoS & spam company explains how they protected a forum from a headless browser bot spam. They fingerprinted the browser using a Javascript objects scanner and based their protection on detecting the window._phantom() and window.callPhantom() references with the following code snippet :

function isPhantomJS() {
	!!window._phantom || // PhantomJS extends window object with _phantom
	!!window.callPhantom; // Function injected by PhantomJS

As we saw in the previous part, you can simply remove these references to evade this kind of protections which makes headless browsers pretty hard to detect. Sure you can still put a reliable captcha on all your post pages as a last resort but visitors won't like it.

4. Countermeasures

This post by ShapeSecurity shows plenty of ways to detect a PhantomJS visitor. Even though most of them can be easily bypassed, some of them use elaborate Javascript that is not handled as it should because of a different implementation. As I previously said, using modern captchas is a reliable way to tell a legitimate user from a headless browser based bot, but you obviously can not put captchas on every page since user experience is way more important than security most of the time.

To conclude, it is safe to say that headless browsers usage in cybercriminal activities will only increase and will require some drastic answers.