Skip to content

Instantly share code, notes, and snippets.

@gfx
Last active July 24, 2021 01:30
Show Gist options
  • Save gfx/230010980c04415bb602afdfd5165ed8 to your computer and use it in GitHub Desktop.
Save gfx/230010980c04415bb602afdfd5165ed8 to your computer and use it in GitHub Desktop.
Explain why 001-CVE-2021-23410 is invalid

CVE-2021-23410 is invalid because the PoC has nothing to do with the msgpack module and any other serializers.

The PoC is something like this:

var assert = require('assert');
var msgpack = require('msgpack');
function sleep(ms) {
return new Promise((resolve) => {
setTimeout(resolve, ms);
});
}
async function init() {
var normal = {"a" : 1, "b" : 2, "c" : [1, 2, 3]};
var malicious = msgpack.pack({exploit : function(){require('child_process').exec('echo code_executed!;sleep 3', function(error,stdout, stderr) { console.log(stdout) });}(),}); 
var rce = msgpack.unpack(malicious);
assert.deepEqual(rce, normal);
}

init();

Extracting the { exploit: ... }, wrap it with console.log to print, and format it:

console.log({
  exploit: (function () {
    require("child_process").exec(
      "echo code_executed!;sleep 3",
      function (error, stdout, stderr) {
        console.log(stdout);
      }
    );
  })(),
});

It shows "{ exploit: undefined }" and then "code executed!" as the PoC does. This is because the "function () { ... }" expression is an anonymous function and the trailing "()" call the fucntion object immediately. Therefore, the fact that "code executed! is printed does not mean the serializer has a vulnerability.

// Sited from https://snyk.io/vuln/SNYK-JS-MSGPACK-1296122
// and format it for readability.
var assert = require("assert");
var msgpack = require("msgpack");
function sleep(ms) {
return new Promise((resolve) => {
setTimeout(resolve, ms);
});
}
async function init() {
var normal = { a: 1, b: 2, c: [1, 2, 3] };
var malicious = msgpack.pack({
exploit: (function () {
require("child_process").exec(
"echo code_executed!;sleep 3",
function (error, stdout, stderr) {
console.log(stdout);
}
);
})(),
});
var rce = msgpack.unpack(malicious);
assert.deepEqual(rce, normal);
}
init();
// extracted the value of `exploit` and print it instead of serialize.
// this shows "code_executed!" because the expression "function () {...}" is an anonymous function
// and the trailing "()" calls the function immediately. Therefore, the value of `exploit` is `undefined`,
// meaning not related to serializers.
// In other words, replacing "msgpack.pack" with "JSON.stringify" results in the same output.
//
// FYI if you run this file with nodejs, you'll see:
// $ node test.js
// { exploit: undefined }
// code_executed!
var exploit = (function () {
require("child_process").exec(
"echo code_executed!;sleep 3",
function (error, stdout, stderr) {
console.log(stdout);
}
);
})();
console.log({
exploit: exploit,
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment