
Struts2 की कमज़ोरियाँ S2-045, S2-055 और Jackson की कमज़ोरियाँ CVE-2017-7525, CVE-2017-15095 की जाँच रिपोर्ट
केवल मुख्य बिंदुओं को संक्षेप में, पढ़ने में आसान सारांश लेख प्रकाशित किया गया है। पहले सामान्य जानकारी जानने वालों या समय की कमी वालों के लिए अनुशंसित।
2017年12月1日 को Struts2 का सुरक्षा अपडेट जारी किया गया था। जारी होने से पहले ही मेलिंग सूची में यह बात फैल गई थी कि Jackson (जावा में लोकप्रिय JSON लाइब्रेरी) की कमज़ोरी इससे संबंधित है, और कंपनी के आंतरिक सिस्टम और टूल्स में Jackson का उपयोग करने वाले लेखक को भी इस बात की चिंता थी कि वास्तव में इसका स्वरूप क्या है।
वास्तव में जारी की गई सामग्री के अनुसार, निम्नलिखित दो सुरक्षा समस्याओं को ठीक किया गया था। Jackson के घटक jackson-databind की कमज़ोरी केवल S2-055 को प्रभावित करती है।
REST प्लगइन में पहले से JSON-lib का उपयोग करने वाला हैंडलर और Jackson का उपयोग करने वाला हैंडलर शामिल था, जिसे उपयोगकर्ता चुन सकता था। S2-054 में डिफ़ॉल्ट हैंडलर को Jackson में स्विच किया गया, और S2-055 में Jackson के पुराने संस्करण को नवीनतम में अपडेट किया गया, यही इस सुधार का पूरा चित्र प्रतीत होता है।
तो आखिर CVE-2017-7525 कैसी कमज़ोरी है? लेखक स्वयं आमतौर पर जावा में JSON प्रसंस्करण के दौरान Jackson का उपयोग करता है, इसलिए 2, 3 दिसंबर के सप्ताहांत में इस समस्या की जांच की, यही इस लेख का विषय है।
नमूना कोड सत्यापन के लिए लेखक का वातावरण:
Adam Caudill के ब्लॉग पर CVE-2017-7525 की व्याख्या प्रकाशित की गई है।
लेखक अपने शब्दों में संक्षेप में बताए तो, jackson-databind JSON को Java ऑब्जेक्ट में मैप करने की सुविधा (ObjectMapper वर्ग) प्रदान करता है।
यहाँ ObjectMapper.enableDefaultTyping() को कॉल करके JSON में स्वतंत्र रूप से एम्बेड किए गए क्लास नाम से मैप करना संभव हो जाता है।
"इनपुट JSON में क्लास नाम निर्दिष्ट करना संभव" - यह सुनते ही कुछ लोगों को बुरा पूर्वाभास हुआ होगा, लेकिन वही बुरा पूर्वाभास CVE-2017-7525 के रूप में सच हुआ।
कमज़ोरी की व्याख्या में जाने से पहले, आइए समझें कि आखिर ऐसी सुविधा क्यों लागू की गई।
jackson-databind द्वारा deserialize के बुनियादी उपयोग के लिए कृपया निम्नलिखित नमूना कोड देखें। (इस लेख में Jackson के नमूना कोड में Groovy का उपयोग किया गया है। @Grab का उपयोग करके jackson-databind के संस्करण को आसानी से स्विच करना सुविधाजनक है।)
उपरोक्त नमूना कोड में सरलता से "animal" कुंजी सीधे Animal वर्ग में मैप हो सकती है। ठीक है, निम्नलिखित स्थितियों में क्या होगा?```java class Zoo { Animal animal; }
abstract class Animal { String name; protected Animal() { } }
class Dog extends Animal { double barkVolume; Dog() { } }
class Cat extends Animal { boolean likesCream; int lives; Cat() { } }
इस कॉन्फ़िगरेशन में, "animal" की की-वैल्यू Dog क्लास को इंगित करने वाली और Cat क्लास को इंगित करने वाली दो तरह की स्थितियाँ उत्पन्न होती हैं। इसलिए, यह तय करने के लिए अतिरिक्त जानकारी की आवश्यकता है कि किस क्लास से मैपिंग की जाए।
इसे हल करने के लिए, jackson-databind ने एक कस्टम प्रक्रिया को शामिल किया है जो JSON में मैप किए जाने वाले क्लास के नाम को एम्बेड करने की अनुमति देती है। उदाहरण के लिए, नीचे दिए गए तरीके से, "animal" की को एक ऐरे में बदल दिया जाता है और पहले एलिमेंट में क्लास का नाम निर्दिष्ट किया जाता है।```
{"animal":["Dog",{"name":"dog1","barkVolume":1.2}]}
इसके परिणामस्वरूप ObjectMapper.readValue() "animal" कुंजी की सामग्री को Dog वर्ग के रूप में पहचानता है और मैपिंग करता है।
बेशक, इस रूप में, यह निर्धारित नहीं किया जा सकता कि "animal" कुंजी की सामग्री मूल रूप से एक सरणी थी या इसमें jackson-databind का अद्वितीय वर्ग नाम जानकारी शामिल थी।
इसे स्विच करने का तरीका ObjectMapper.enableDefaultTyping() विधि है।
इसके अलावा वर्ग पर @JsonTypeInfo एनोटेशन को परिभाषित करने का भी एक तरीका है। विस्तृत जानकारी के लिए नीचे दिए गए Jackson दस्तावेज़ देखें।
वास्तव में ObjectMapper.enableDefaultTyping() विधि का उपयोग करने वाला एक नमूना कोड नीचे दिखाया गया है।
जैसा कि ऊपर देखा गया है, वर्ग नाम के बाद उसके गुणों को JSON में देकर, कुछ सीमाओं के बावजूद, किसी भी वर्ग को किसी भी गुण के साथ उत्पन्न करना संभव हो जाता है। इसका दुरुपयोग CVE-2017-7525 की कमजोरी में किया गया था, और इसका कारण संभवतः निम्नलिखित रिपोर्ट थी:
Jackson जैसे Java में सामान्यतः उपयोग किए जाने वाले serialize/deserialize लाइब्रेरीज़ के बारे में, वर्ग नामों आदि के संचालन से मनमाना कोड निष्पादन की ओर ले जाने वाले खतरे की रिपोर्ट की गई है, और वास्तव में कौन से वर्ग खतरनाक हैं, इसकी विशिष्ट वर्ग नामों की सूची दी गई है।
यह इसके जवाब में था या नहीं, यह स्पष्ट नहीं है, लेकिन तिथि के अनुसार, उपरोक्त रिपोर्ट के पहले कमिट के तुरंत बाद, jackson-databind में निम्नलिखित Issue खोला गया और समाधान शुरू हुआ।
वास्तव में इस कमजोरी का शोषण करने वाला JSON डेटा और Java कोड कैसा होगा? इस Issue में संबोधित jackson-databind 2.8.9 के परीक्षण कोड में एक संकेत है:
इस परीक्षण कोड के आधार पर, कार्यशील सत्यापन के लिए समायोजित एक नमूना कोड नीचे दिया गया है।