You were thinking about trying out Node.js for your company and were just about to roll up your sleeves and write a few lines of code when you were shocked by the bug. Node.js has discovered a major vulnerability in remote code execution using the deserialization vulnerability of Node.js. Mom, such a big bug, is it impossible to meet the KPI of node.js pilot this year?


What is this loophole?

After reading the above three articles, all of them mention a Node.js library for Node-serialize. The library provides the API unserialize function that provides the possibility of injection:


var serialize = require('node-serialize'); var payload = '{"rce":"_? ND_FUNC? _function(){require(\'child_process\').exec(\'ls /\',function(error, stdout, stderr) { console.log(stdout)}); }} '() "; serialize.unserialize(payload);Copy the code

There’s this code inside unserialize (I’ve reworked it a bit for simplicity) :


if (obj[key].indexOf('_? ND_FUNC? _') === 0) { obj[key] = eval('(' + obj[key].substring('_? ND_FUNC? _'.length) + ')'); }Copy the code

So let’s simplify this,


eval('(function(){require(\'child_process\').exec(\'ls /\',function(error, stdout, stderr) { console.log(stdout)}); }} () ") ')Copy the code

To simplify the example, if the user types {“rce”:”_? ND_FUNC? _process.exit()”} to stop the server.


eval('(process.exit())')
Copy the code

Is this a major flaw in Node.js?

Take a look at what the National Security Vulnerability Sharing Platform has to say:

The vulnerability affects all existing versions of Node.js because it involves IIFE function expressions, according to tests by vulnerability researchers. According to the census results of CNVD secretariat, currently there are about 68,000 servers using Node.js operating environment directly demarcated on the Internet, among which the top five countries and regions are the United States (58.9%), China (23.2%), The United Kingdom (4.1%), the Netherlands (3.6%), Germany (3.0%). Because a widely used WEB application development framework named Express is based on node.js operating environment, according to the preliminary survey results of THE CNVD secretariat, the vulnerability may affect more than 700,000 WEB servers, CNVD will further carry out a precise assessment of the actual threat impact of the vulnerability. Do a good job of emergency response for domestic users.

There are several points in this paragraph that need to be discussed.

Because it involves IIFE function expressions, the vulnerability affects all existing versions of Node.js: The vulnerability is in the eval function, not IIFE; A link to the corresponding CVE (common Vulnerability list) is provided at the beginning of this article cve.mitre.org/cgi-bin/cve… :

Apache Struts 2.3.20.x before 2.3.20.3, 2.3.24.x before 2.3.24.3, and 2.3.28.x before 2.3.28.1, when Dynamic Method Invocation is enabled, allow remote attackers to execute arbitrary code via vectors related to an ! (exclamation mark) operator to the REST Plugin.

The example is Apache Struts, where an attacker can implement an attack remotely via dynamic invocation. This is analogous to the eval problem.

Because a widely used WEB application development framework named Express is based on node.js operating environment, according to the preliminary survey results of the CNVD secretariat, the vulnerability may affect more than 700,000 WEB servers: There is a problem with the Node-serialize package, so it doesn’t make sense to deduce that Node.js is a problem and then say that the 700,000 servers using Express are a problem.

Narrowly speaking, this vulnerability is caused by the node-serialize class library using eval, a function not recommended by the JavaScript community. This is not a Node.js bug, because the problem does not appear in the node.js source code.

How big is the impact? The project’s star on Github is 20. On npmjs.org, you can see that there are several libraries that rely on it, but the number of downloads per month is even in the single digits. So the idea of over 700,000 being affected is completely false.

Broadly speaking, this is a JavaScript problem. JavaScript provides the eval function, which evaluates a string of JavaScript code. But:

Don ‘t use the eval needlessly! eval() is a dangerous function, Which executes the code it’s passed with the privileges of the caller. If you run eval() with a string that could be affected by a malicious party, You may end up running malicious code on the user’s machine with the permissions of your webpage/extension. More importantly, third party code can see the scope in which eval() was invoked, Which can lead to possible attacks in ways to which the similar Function is not susceptible to Developer.mozilla.org/zh-CN/docs/…

Eval has long been deprecated in JavaScript.

Anyway, this is not a Bug in Node.js itself, let alone a major bug!


How to fix this bug?

For Node-serialize, this vulnerability cannot be fixed from the source code. The goals of this library are:

Serialize an object including it’s function into a JSON

Serialize an object into a JSON string, including functions on the object. In deserialization, string functions must be converted to functions via eval or new Function(). This is an insecure way to achieve the library’s goals, so whatever Node-serialize does with checking incoming strings, it leaves insecure implications.

So the authors offer two suggestions:

  • Use this library in a closed internal environment, completely isolating them from potential injectors; For example, only serialized objects are passed from the back-end server to the front-end server, and HTTPs is used instead of HTTP;
  • Encrypts serialized data using asymmetric encryption (RSA) to avoid tampering.

In our view, the only way to fix or avoid this vulnerability is to stop using the node-serialize library and stop using JavaScript crap like Eval, which gives injectors endless possibilities, especially in back-end code.


Foreign magazine gentleman want to say

The author of the first three articles should stop trying to make big news about security research. The scope of the breach is literally satellite-based. You can look at the articles of Exploiting node.js deserialization bug for Remote Code Execution in other countries at the beginning, and the sample codes and screenshots in China are all the same as this article. Could the source be indicated in the translation? Also check out the comments below where reader Lukas has pointed out the problems with the original – clickbait, overblown, and not being clear about what the problems are.

Eval can’t be used. Eval can’t be used. Eval can’t be used. Of course, the new Function doesn’t work either, it’s an infinite pit. A tool such as ESLint can be used to check this.