FlawOpen

flawopen.com/कमज़ोरियाँ/JavaScript प्रोटोटाइप प्रदूषण

JavaScript प्रोटोटाइप प्रदूषण

उच्च गंभीरता CWE-1321 सप्लाई चेन और रनटाइम
सरल व्याख्या — साझा नियम-पुस्तिका

ऐसी कार्यशाला सोचें जहाँ हर नया उपकरण अपने सेटिंग्स में उत्तर न मिलने पर साझा नियम-पुस्तिका देखता है। यदि कोई कर्मचारी हमलावर के नियंत्रण वाला नियम उसमें लिख दे, तो दूसरे उपकरण उसे default मान सकते हैं। Prototype pollution में असुरक्षित dynamic property writes किसी object का prototype बदल सकते हैं, कभी-कभी Object.prototype भी। असर अपने-आप global नहीं होता; बाद का application code inherited property पर भरोसा करे तभी प्रभाव पड़ता है।

लक्ष्य:Server या browser का JavaScript जो untrusted keys merge करता है या उपयोगकर्ता-नियंत्रित property paths लिखता है
प्रवेश मार्ग:__proto__ जैसी untrusted keys, या असुरक्षित write तक पहुँचने वाला constructor.prototype path
प्रभाव:यह reachable gadget पर निर्भर है: logic बदलना, denial of service, XSS या कुछ server-side मामलों में code execution; इनमें से कुछ भी अपने-आप नहीं होता
उपाय:Schema या allowlist से validate करें; untrusted keys के लिए Map या बिना prototype वाले dictionary का उपयोग करें

मुख्य अवधारणाएँ और उपतंत्र शब्द

Object.prototype
साझा prototype जिसे सामान्य objects inherit करते हैं। इसका pollution कई objects को प्रभावित कर सकता है, लेकिन हर JavaScript object या हर realm को नहीं।
__proto__
सामान्य objects का पुराना accessor जो उनका prototype पढ़ता या सेट करता है। JSON text में यही spelling पहले साधारण property name है, जब तक बाद का code इसे असुरक्षित ढंग से न संभाले।
पुनरावर्ती डीप मर्ज
यह nested keys को पढ़कर दूसरे object में लिखने वाला copier है। Untrusted keys यदि prototype-संबंधित properties या unsafe paths चुन सकें तो यह जोखिमपूर्ण है।
CWE-1321
Object prototype attributes में अपर्याप्त रूप से नियंत्रित बदलाव। कमजोरी अनियंत्रित mutation है; आगे का असर reachable application behavior पर निर्भर करता है।

हमले का चरण-दर-चरण प्रवाह

चरण 1

अविश्वसनीय property input

Endpoint हमलावर-नियंत्रित object keys स्वीकार करता है। अपना __proto__ property वाला JSON parse करना अकेले prototype नहीं बदलता।

चरण 2

असुरक्षित dynamic write

Recursive merge या path setter उन keys का अनुसरण करके हर path segment जाँचे बिना dynamic writes करता है।

चरण 3

लक्ष्य या साझा prototype में बदलाव

Target और write sequence के आधार पर operation target का prototype बदल सकता है या Object.prototype जैसे shared prototype तक पहुँच सकता है। ये अलग परिणाम हैं।

चरण 4

प्रभाव gadget पर निर्भर है

बाद का gadget किसी security-sensitive operation में inherited value पढ़ता है। नतीजा उस gadget पर निर्भर है; authentication bypass या code execution मानकर न चलें।

तंत्र और मूल कारण

JavaScript में property lookup prototype chain का अनुसरण करता है। Vulnerable merge या path setter untrusted keys जैसे __proto__ या constructor.prototype को prototype तक write निर्देशित करने दे सकता है। JSON.parse से बना अपना __proto__ field खुद pollution नहीं है; बाद के code को unsafe assignment से उसकी व्याख्या करनी होगी। Target prototype बदलने से वही target प्रभावित होता है; Object.prototype बदलने से उसे inherit करने वाले सामान्य objects प्रभावित होते हैं। Security impact के लिए कोई अलग gadget उस inherited property का उपयोग करे।

utils.js (कमज़ोर recursive merge)असुरक्षित
// असुरक्षित: हमलावर-नियंत्रित keys recursive writes तक पहुँचती हैं
function merge(target, source) {
    for (const key in source) {
        const value = source[key];
        if (value && typeof value === 'object') {
            if (!target[key]) target[key] = {};
            merge(target[key], value);
        } else {
            target[key] = value;
        }
    }
    return target;
}
// JSON.parse अपना __proto__ data property बनाता है; जोखिम unsafe merge में है।
const input = JSON.parse('{"__proto__": {"isAdmin": true}}');
merge({}, input);
utils.js (allowlist से profile parse)सुरक्षित
// सुरक्षित: केवल endpoint द्वारा स्वीकार किए गए fields कॉपी करें
const PROFILE_KEYS = new Set(['displayName', 'theme']);

function parseProfile(input) {
    if (!input || typeof input !== 'object' || Array.isArray(input)) {
        throw new TypeError('profile must be an object');
    }

    const profile = Object.create(null);
    for (const key of Object.keys(input)) {
        if (!PROFILE_KEYS.has(key)) continue;
        const value = input[key];
        if (typeof value !== 'string' || value.length > 80) {
            throw new TypeError('invalid profile field');
        }
        profile[key] = value;
    }
    return profile;
}

हमले और exploit का क्रम

रक्षात्मक इंजीनियरिंग और रोकथाम नियम

अक्सर पूछे जाने वाले प्रश्न

क्या JSON.parse() अपने-आप prototype दूषित करता है?

नहीं। JSON.parse() __proto__ नाम की own data property बनाता है और inherited setter नहीं चलाता। बाद का merge या assignment setter चलाए तो जोखिम है। देखें क्या JSON.parse() Prototype Pollution करता है?

क्या Object.freeze(Object.prototype) इसे ठीक करता है?

यह frozen Object.prototype में लिखने से रोक सकता है, लेकिन setter को किसी एक object का prototype बदलने से या अन्य prototypes को प्रभावित करने से नहीं रोकता। Built-ins बढ़ाने वाली libraries भी टूट सकती हैं। इसे केवल defense-in-depth मानें, data-handling fix नहीं।

क्या TypeScript सुरक्षित है?

नहीं। Types runtime पर मिट जाते हैं। Record<string, string> घोषित value में भी __proto__ key हो सकती है। Untrusted keys validate करें और objects सुरक्षित तरीके से बनाएँ।

संबंधित सुरक्षा विषय और घटना विश्लेषण देखें:पूरा सुरक्षा निर्देशिका →