Investments

Findmortgagehomemortgages Mortgage Find Mortgage Home Mortgages Find Mortgage Home Mortgages Szh Hamp Hamp Find Mortgage Home Mortgages MK2 - 博客园

Findmortgagehomemortgages Mortgage Find Mortgage Home Mortgages Find Mortgage Home Mortgages Szh Hamp Hamp Find Mortgage Home Mortgages

Hamp
随笔- 177  文章- 24  评论- 257 
2012年1月1日
Defense hash algorithm collision 防御hash算法冲突导致拒绝服务器

问题

一篇#2011-003 multiple implementations denial-of-service via hash algorithm collision 文章,引起了 Web 应用安全领域的骚动。

这种hash算法冲突的原理到底是什么?可以看看一下两篇以PHP为例子的说明文章:

解决办法

既然是语言层面的hash算法冲突导致的,那么这种冲突就无法避免了。
但是我们可以限制Hash key的数量来避免。

所以可以进行一下设置解决此问题:

  • 限制请求大小 (只能指标不治本,因为PHP版本的话,700KB的数据就足以发起攻击)
  • 限制请求key的数量 (这可以基本解决问题,除非应用无法预知最大的key数量)
  • 只接受允许的key (这是终极方法,但需要保证开发记得配置新增的key)

在Nodejs防御此问题

虽然在目前为止还没看到对Nodejs造成攻击的具体方法,但是还是以防范于未然为原则,需要对此问题做好充分的防御措施。

Nodejs 的攻击方法已经出现,具体测试结果可以查看 Hash algorithm collision in Nodejs

由于我个人一直使用的是 connect ,所以我以 connect 为示例说明吧 ^_^

使用 connect.limit 限制 request-body-size

Issue #446 已有同学提出此问题了,@TJ回复如下:

we have limit() for this, which works for any request body. Even without this specific issue you could exhaust resources reasonably easily without some form of limiting

好吧,直接上 connect.limit 模块解决

connect()
 .use(connect.limit('1mb'))
 .use(handleRequest)

修改 qs 模块,让其支持 keys-limit 和 allow-keys

querystring.js

PS: 提了pull request,但是估计在没有真实攻击示例放出来之前,是不会被接受的。

/**
 * Parse the given str.
 */

function parseString(str, options) {};
 for (var i = 0, l = options.keys.length; i < l; i++) {}
 }
 return String(str)
 .split('&', limit)
 .reduce(function(ret, pair){} catch(e) {}

  var eql = pair.indexOf('=')
 , brace = lastBraceInKey(pair)
 , key = pair.substr(0, brace || eql);
  if (keys && !keys[key]) {}
  var val = pair.substr(brace || eql, pair.length)
  val = val.substr(val.indexOf('=') + 1, val.length);

  // ?foo
  if ('' == key) key = pair, val = '';

  return merge(ret, key, val);
 }, {} }).base;
}


/**
 * Parse the given query `str` or `obj`, returning an object.
 *
 * Options: (only effect on parse string)
 *
 * - `limit` parse string split limit.
 * - `keys` which keys need to be parse.
 *
 * @param {} str | {} obj
 * @param {} options
 * @return {}
 * @api public
 */

exports.parse = function(str, options) {};
 return 'object' == typeof str
 ? parseObject(str)
 : parseString(str, options);
};

还需要让 connect.query 模块 传递options参数给 qs.parse()

module.exports = function query(options){};
 next();
 };
};

同样 connect.urlencoded 模块也需要将options参数传递给 qs.parse()

 req.on('end', function(){};
 next();
  } catch (err){}
 });

全部组合起来

var qsOptions = {};
connect()
 .use(connect.limit('1mb'))
 .use(connect.query(qsOptions))
 .use(connect.bodyParser(qsOptions))
 .use(handleRequest)

防范 http header 攻击

请求的 http header 也会导致hash冲突,在V8层面未修复hash算法之前,可以通过简单的 http_patch.js 修复此问题:

var http = require('http');

var IncomingMessage = http.IncomingMessage;
var _addHeaderLine = IncomingMessage.prototype._addHeaderLine;

// limit http header number
IncomingMessage.prototype._addHeaderLine = function(field, val) {} else if (this.__headerCount__ >= 100) {}
 _addHeaderLine.apply(this, arguments);
 this.__headerCount__++;
};

最后

2011年末,苦逼的程序员还在为这个安全漏洞写补丁,打补丁,想各种解决方法。
2012年或许还会有各种各样的问题,我们一起勇敢面对吧。
Happy New Year!

posted @ 2012-01-01 00:49 MK2 阅读(318) 评论(4) 编辑
2011年12月14日
fibonacci(40) benchmark

Node.js is Cancer show a wrong way to use nodejs.
But the test code Fibonacci is so funny.
I implement the fibonacci function in other Dynamic Languages for comparison testing.

Languages

Dynamic

Static

If you want to help add more dynamic languagues, please leave the implement code in comments.

Results

(^_^) c > go > luajit > nodejs > pypy > lua > python > php > perl > ruby1.9.3 > ruby1.8.5 (T_T)

LanguageTimesPosition
c0m1.606s#0
go0m1.769s#1
node + cpp module0m2.216s#2
luajit0m2.583s#3
nodejs0m5.124s#4
pypy0m7.562s#5
lua0m34.492s#6
python1m11.647s#7
php1m28.198s#8
perl2m34.658s#9
ruby 1.9.34m40.790s#10
ruby 1.8.54m41.942s#11

lua use local function will get better performance.

Test Codes

nodejs

function fibonacci(n) {}
 return fibonacci(n - 2) + fibonacci(n - 1);
}

console.log(fibonacci(40));

run

$ time node fibonacci.js
165580141

real 0m5.153s
user 0m5.124s
sys 0m0.012s

nodejs + cpp module

cppfibonacci.cpp

#include 
#include 

using namespace v8;

int fibonacci(int n) {}
 return fibonacci(n - 1) + fibonacci(n - 2);
}

Handle Fibonacci(const Arguments& args) {}
 Local integer = args[0]->ToInteger();
 int r = fibonacci(integer->Value());

 return scope.Close(Integer::New(r));
}

void RegisterModule(v8::Handle target) {}

// Register the module with node.
NODE_MODULE(cppfibonacci, RegisterModule);

wscript

#!/usr/bin/env python

def set_options(ctx):
 ctx.tool_options('compiler_cxx')

def configure(ctx):
 ctx.check_tool('compiler_cxx')
 ctx.check_tool('node_addon')

def build(ctx):
 t = ctx.new_task_gen('cxx', 'shlib', 'node_addon')

 t.source = ['cppfibonacci.cpp']

 # Must be same as first parameter in NODE_MODULE.
 t.target = 'cppfibonacci'

cppfibonacci.js

var fibonacci = require('./build/default/cppfibonacci').fibonacci;
console.log(fibonacci(40));

run

$ node-waf configure
$ node-waf build
$ time node cppfibonacci.js
165580141

real 0m2.224s
user 0m2.216s
sys 0m0.008s

python2.4.3 && python2.6.7 && pypy1.7

def fibonacci(n):
 if n < 2:
 return 1
 return fibonacci(n - 2) + fibonacci(n - 1)

print fibonacci(40)

run

$ time python2.4.3 fibonacci.py
165580141

real 1m11.667s
user 1m11.647s
sys 0m0.002s

$ time python2.6.7 fibonacci.py
165580141

real 1m9.837s
user 1m9.792s
sys 0m0.006s

$ time ./pypy-1.7/bin/pypy fibonacci.py
165580141

real 0m7.608s
user 0m7.562s
sys 0m0.031s

perl

sub fibonacci {}
 return fibonacci($n - 2) + fibonacci($n - 1);
}

print fibonacci(40), "\n";

run

$ time perl fibonacci.pl
165580141

real 2m34.777s
user 2m34.658s
sys 0m0.004s

php


run

$ time php fibonacci.php

165580141
real 1m28.364s
user 1m28.198s
sys 0m0.039s

ruby1.8.5 && ruby1.9.3

def fibonacci(n)
 if n < 2
 return 1
 end
 return fibonacci(n - 2) + fibonacci(n - 1)
end

puts fibonacci(40)

run

$ time ruby1.8.5 fibonacci.rb
165580141

real 5m43.132s
user 4m41.942s
sys 1m0.653s

$ time ruby1.9.3 fibonacci.rb
165580141

real 5m41.714s
user 4m40.790s
sys 1m0.661s

lua && luajit

function fibonacci(n)
 if n < 2 then
 return 1
 end
 return fibonacci(n - 2) + fibonacci(n - 1)
end

io.write(fibonacci(40), "\n")

run

$ time ./lua-5.1.4/src/lua fibonacci.lua 
165580141

real 0m34.514s
user 0m34.492s
sys 0m0.004s

$ time ./LuaJIT-2.0.0-beta9/src/luajit fibonacci.lua 
165580141

real 0m2.598s
user 0m2.583s
sys 0m0.001s

local function should be faster:

local function fibonacci(n)
 if n < 2 then
 return 1
 end
 return fibonacci(n - 2) + fibonacci(n - 1)
end

io.write(fibonacci(40), "\n")

$ time ./lua-5.1.4/src/lua fibonacci.lua.local
165580141

real 0m31.737s
user 0m31.549s
sys 0m0.001s

$ time ./LuaJIT-2.0.0-beta9/src/luajit fibonacci.lua.local
165580141

real 0m2.227s
user 0m2.225s
sys 0m0.001s

c

#include 

int fibonacci(n) {}
 return fibonacci(n - 2) + fibonacci(n - 1);
}

int main() {}

run

$ gcc fibonacci.c
$ time ./a.out 
165580141

real 0m3.434s
user 0m3.427s
sys 0m0.000s

Compilation with optimization:

$ gcc -O2 fibonacci.c
$ time ./a.out 
165580141

real 0m1.607s
user 0m1.606s
sys 0m0.001s

@fool: How about C++ meta programming, it’s a bit of cheating

#include 

template
struct fibonacci {};
};

template<>
struct fibonacci<1> {};
};

template<>
struct fibonacci<0> {};
};

int main(int argc, char *argv[])
{}

run

$ g++ fibonacci.template.cpp 
$ time ./a.out
165580141

real 0m0.002s
user 0m0.001s
sys 0m0.001s

go

package main

import "fmt"

func fibonacci(n int) int{}
 return fibonacci(n - 2) + fibonacci(n - 1)
}

func main() {}

run

$ 6g fibonacci.go
$ 6l fibonacci.6
$ time ./6.out
165580141

real 0m1.770s
user 0m1.769s
sys 0m0.001s

Conclusion

nodejs is very FAST.
luajit 2X faster than nodejs, Shocking.

posted @ 2011-12-14 22:21 MK2 阅读(183) 评论(1) 编辑
2011年11月23日
[nodejs]保证你的程序死了还能复活:forever and forever webui

forever

A simple CLI tool for ensuring that a given script runs continuously (i.e. forever).
一个非常简单的CLI工具,让你的程序持续运行。

安装forever: nodejitsu/forever

$ [sudo] npm install forever -g

Demo: 进程重启超过5次后将不再运行

$ forever examples/error-on-timer.js -m 5

forever-webui

eFindmortgagehomemortgages Mortgage Find Mortgage Home Mortgages Find Mortgage Home Mortgages Szh Hamp Hamp Find Mortgage Home Mortgages MK2 - 博客园o f Find Mortgage Home Mortgages v Find Mortgage Home Mortgages Find Mortgage Home Mortgages Mortgages hFindmortgagehomemortgages Mortgage Find Mortgage Home Mortgages Find Mortgage Home Mortgages Szh Hamp Hamp Find Mortgage Home Mortgages MK2 - 博客园c s Find Mortgage Home Mortgages Find Mortgage Home Mortgages