FlawOpen

flawopen.com/प्रोटोटाइप प्रदूषण/JSON.parse()

क्या JSON.parse() प्रोटोटाइप प्रदूषण करता है?

CWE-1321: प्रोटोटाइप प्रदूषणसंदर्भ मार्गदर्शिका
संक्षिप्त उत्तर

नहीं। JSON.parse() __proto__ नाम की अपनी डेटा प्रॉपर्टी बनाता है; पार्सिंग विरासत में मिले setter को नहीं चलाती और न ही प्रोटोटाइप बदलती है। जोखिम बाद के कोड में तब आता है जब यह कुंजी setter से कॉपी हो, अविश्वसनीय कुंजियों का recursive merge हो, या हमलावर-नियंत्रित object path पर लिखा जाए।

असुरक्षित कॉपी — केवल स्थानीय लक्ष्य
// JSON.parse डेटा बनाता है; प्रोटोटाइप प्रदूषित नहीं करता।
const input = '{"__proto__":{"isAdmin":true}}';
const parsed = JSON.parse(input);

// Object.assign लक्ष्य पर Set करता है। यहाँ केवल
// इस स्थानीय उदाहरण ऑब्जेक्ट का प्रोटोटाइप बदलता है।
const copied = Object.assign({}, parsed);

Object.getPrototypeOf(copied).isAdmin; // true
Object.prototype.isAdmin;              // undefined
सुरक्षित उपयोग — ज्ञात आकार
// पार्स करें और केवल स्वीकृत फ़ील्ड बनाएं।
const input = '{"theme":"dark","locale":"en","__proto__":{"isAdmin":true}}';
const parsed = JSON.parse(input);
const config = {
  theme:  parsed.theme,
  locale: parsed.locale,
};

// अविश्वसनीय कुंजियों वाले मानचित्र में विरासत setter से बचें।
const options = Object.assign(Object.create(null), parsed);

JSON.parse() प्रदूषण का स्रोत क्यों नहीं है

JSON कुंजी और object literal का prototype setter अलग-अलग क्रियाएँ हैं। JSON parsing नए मान पर अपनी प्रॉपर्टियाँ परिभाषित करती है; यह obj.__proto__ = value नहीं चलाती। बाद के ऑपरेशन अलग व्यवहार कर सकते हैं: Object.assign(target, source) लक्ष्य पर assignment करता है, इसलिए अपनी __proto__ कुंजी लक्ष्य के विरासत वाले setter को चला सकती है। इससे लक्ष्य ऑब्जेक्ट का प्रोटोटाइप बदलता है; केवल इससे Object.prototype नहीं बदलता।

const o = JSON.parse('{"__proto__":{"a":1}}') के बाद Object.hasOwn(o, "__proto__") true है और Object.prototype.a undefined रहता है। बाद में किसी सामान्य लक्ष्य पर यह कुंजी कॉपी करने से लक्ष्य का प्रोटोटाइप बदल सकता है। Object spread setter चलाने के बजाय अपनी प्रॉपर्टियाँ बनाता है, लेकिन असुरक्षित recursive merge या path assignment से नहीं बचाता।

वास्तविक जोखिम कहाँ आता है

पार्स किया हुआ JSON अविश्वसनीय डेटा है, प्रदूषित प्रोटोटाइप नहीं। जोखिम बाद के write sinks पर निर्भर करता है: recursive merge, path setter, या सामान्य ऑब्जेक्ट पर assignment करने वाला copy loop। कमजोर recursive merge __proto__ या constructor.prototype के रास्ते साझा प्रोटोटाइप तक पहुँच सकता है; एक-स्तरीय कॉपी केवल लक्ष्य बदल सकती है। प्रभाव बताने से पहले वास्तविक helper और target की जाँच करें।

केवल JSON parsing नहीं, बल्कि अविश्वसनीय कुंजियाँ जहाँ लिखी जाती हैं वहाँ समीक्षा करें: deep merge helpers, object-path setters और assignment वाले for...in loops। यदि कुंजियाँ उपयोगकर्ता नियंत्रित कर सकता है तो __proto__, constructor और prototype अस्वीकार करें; सत्यापित ज्ञात आकार बनाएँ या बिना प्रोटोटाइप वाला dictionary इस्तेमाल करें।

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

क्या हमेशा reviver से __proto__ हटाना चाहिए?

यदि ऐप को इस कुंजी की आवश्यकता नहीं है तो reviver इसे parsing के समय हटा सकता है। यह defense in depth है, असुरक्षित merge और path-writing को ठीक करने का विकल्प नहीं; constructor.prototype और गैर-JSON स्रोत भी मायने रखते हैं।

क्या Express या body-parser मेरी सुरक्षा करते हैं?

Body parser JavaScript मान बनाता है; वह बाद की copies या merges को सुरक्षित नहीं बनाता। इस्तेमाल किए गए parser और आगे के operations जाँचें। कुछ query-string parsers bracket syntax से nested objects भी बनाते हैं, जो अलग input path है।

क्या JSON.stringify() प्रोटोटाइप प्रदूषण का जोखिम है?

नहीं। Serialization मान पढ़कर JSON text बनाता है और प्रोटोटाइप नहीं बदलता। जोखिम तब लौट सकता है जब उस text को parse करके असुरक्षित sink में भेजा जाए।

संदर्भ

यह भी देखें JavaScript प्रोटोटाइप प्रदूषण: कारण और बचाव क्या JSON.parse(), eval() से सुरक्षित है? क्या lodash.merge() prototype pollution से सुरक्षित है? Object.assign() और Prototype Pollution: क्या सुरक्षित है?