Node.js安全篇·一次沙箱逃逸的闹剧

前面的话:本人项目实际遇上并解决的问题,可能写得不够完善,求大神给个装X的机会,也希望能够给未遇到过此问题的后来者一点提点!

正文:问题是在前一段时间调用一个第三方网站的接口(A接口)时遇上的。

A接口是一个jsonp调用的接口,当前使用get请求时,会返回一个js函数调用,由于我使用的是Node.js的http原生库进行封装的请求库,默认是不会自动处理jsonp的返回数据,所以得自行进行解析。

如,以下是某次请求返回的消息体

  var body = `_jsInvoke({
      "errcode": 1000,
      "errmsg": "Invalid request trace id.",
      "data": [],
      "datetime": "2018-05-02 15:22:53"
  })`

于是,出于一般的思维,我们就使用了new Function进行处理返回的消息体,代码如下:

  var obj = (new Function(`function _jsInvoke(obj) {return obj} return ${body}`))();

Then? 代码正常执行,结果成功返回,没有任何问题,如些正常运行了半个月,直到这一天,我们突然发现在pm2 日志里面突然多次出现一些问题日志。

  [2018-05-10 12:56:23] [Laravel Req Error] 非法请求,已拒绝连接!
  [2018-05-12 08:41:50] [Laravel Req Error] 订单号出错!
  [2018-05-16 17:32:56] [Laravel Req Error] IP黑名单已满!

问题来了时,当时最受关注的是,在一个pm2运行的Node.js项目里面,怎么会有Laravel的日志?因为在pm2中的log日志,是不会显示出错栈跟踪的,所以,我们只能做一些日志跟踪测试,(跟踪过程省略......)

终于,在5月22日早上,奇怪的pm2日志再次出现,而这次我们就迅速定位到上面的用到的new Function处理方法中,而这些错误的pm2日志,正是从里面打印出来的,

奇怪?
new Function里面没有console.log啊?
除非,console.log被调用了,不可能打印出log啊?
对,console.log被调用了,console.log被调用了,console.log被调用了...

好恐怖的现象......现在想起来还有点后怕,幸亏没造成什么损失!

以下,我们来分析一下,问题是怎样产生的,这个现象会造成什么严重效果。

我们都知道:

  1. jsonp请求返回的是一个javascript脚本字符串,并且响应头为Content-Type:text/javascript;
  2. new Function 方法的调用,可以把javascript脚本字符串翻译为javascript语法进行执行;
  3. node.js的变量使用或才函数调用,如果没有严格规定作用域,则会一层层往上追溯到最顶层的对象global中;

所以为什么之前刚接入接口是,能正常执行,是因为接口返回的数据正好是符合我们需要的规范,所以return之后能够把obj当成js对象返回。
但后来,返回的数据变成了如下:

var body = `console.log("这里是错误信息!")`

则new Function里面的字符串就变成了如下:

  var obj = (new Function(`function _jsInvoke(obj) {return obj} return console.log("这里是错误信息!")`))();

于时,console.log就被调用了!


深入一下:
如果请求响应数据是这样子:

var body = `(function() {
  while(true){}
})()`

那么当前进程就一直处于死循环中,直到资源耗尽,进程崩溃!如果对一个正在线上运行的项目,这是致命的!


再深入一下:
如果请求响应数据是这样子:

var body = `this.constructor.constructor("return require('child_process')")()`

呵呵,这样子处理的数据就可以逃逸出去,严重的话,服务器就GG了。

所以,在任何第三请求以及回调中,一定要经过严格的数据处理,不然最后自己的服务器被夺走了,也没发现问题!

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 作者: Manuel Kiessling 翻译: goddyzhao & GrayZhang & MondayC...
    紫月凌枫阅读 2,406评论 5 26
  • 工厂模式类似于现实生活中的工厂可以产生大量相似的商品,去做同样的事情,实现同样的效果;这时候需要使用工厂模式。简单...
    舟渔行舟阅读 7,910评论 2 17
  • github地址,欢迎大家提交更新。 express() express()用来创建一个Express的程序。ex...
    Programmer客栈阅读 2,626评论 0 1
  • Node.js是目前非常火热的技术,但是它的诞生经历却很奇特。 众所周知,在Netscape设计出JavaScri...
    w_zhuan阅读 3,642评论 2 41
  • 还是喜欢在这样寂静的夜,让灵魂沉浸在音乐里,任思绪在无尽的暗夜里游走。 趁着倒水的间隙,悄悄地给小子拉好被他踢到一...
    葛芳阅读 387评论 0 1