सामान्य कमजोरियों की सूची
स्मार्ट कॉन्ट्रैक्ट कमजोरियां, एक बार तैनात होने पर, विनाशकारी और अक्सर अपरिवर्तनीय परिणामों का कारण बन सकती हैं। इन कमजोरियों का शोषण ब्लॉकचेन सुरक्षा के लिए एक बड़ी चुनौती पेश करता है, जिसके परिणामस्वरूप अरबों डॉलर की संपत्ति चोरी हो जाती है और उपयोगकर्ता का विश्वास कम होता है। इसलिए, मजबूत स्मार्ट कॉन्ट्रैक्ट सुरक्षा प्राप्त करना सर्वोपरि है। इसके लिए केवल ब्लॉकचेन पर कोड तैनात करने से कहीं अधिक की आवश्यकता होती है। इसके लिए कठोर सुरक्षित कोडिंग प्रथाओं, गहन परीक्षण, और अक्सर, स्वतंत्र स्मार्ट कॉन्ट्रैक्ट ऑडिट की आवश्यकता होती है ताकि मुद्दों का दुरुपयोग होने से पहले उनकी पहचान की जा सके। कुख्यात DAO हैक जैसे रीएंट्रेंसी हमलों से लेकर सूक्ष्म तर्क दोषों और इंटीजर ओवरफ्लो जैसी इथेरियम कमजोरियों तक - सामान्य कमियों को समझना, रोकथाम की दिशा में पहला महत्वपूर्ण कदम है। यह पृष्ठ जागरूकता बढ़ाने और विकेन्द्रीकृत पारिस्थितिकी तंत्र में सुरक्षित विकास को बढ़ावा देने के लिए अक्सर होने वाली स्मार्ट कॉन्ट्रैक्ट कमजोरियों का एक आवश्यक सिंहावलोकन प्रदान करता है।
- Reentrancy
- Unexpected Ether
- DoS
- Overflow
- tx.origin Authentication
- Access Control
- Weak Randomness
- Hash Collision
- Precision Loss
- msg.value in loop
- ecrecover
- Replay
- Inheritance Order
- MEV
रीएंट्रेंसी (Reentrancy) स्मार्ट कॉन्ट्रैक्ट की सबसे शुरुआती और सबसे विनाशकारी कमजोरियों में से एक है, जो The DAO हैक जैसे महत्वपूर्ण ऐतिहासिक कारनामों के लिए जिम्मेदार है, जिसके कारण Ethereum का हार्ड फोर्क हुआ। यह अभी भी एक गंभीर खतरा है जिसके संभावित भयानक परिणाम हो सकते हैं, जो कॉन्ट्रैक्ट से सारा फंड निकाल लेने में सक्षम है।
यह भेद्यता एक आम कोडिंग एंटी-पैटर्न से उत्पन्न होती है, जो अक्सर Web2 की आदतों से आती है: कॉन्ट्रैक्ट की आंतरिक स्थिति (state) (जैसे, यूज़र बैलेंस) को अपडेट करने से पहले बाहरी इंटरैक्शन (जैसे Ether ट्रांसफर करना या किसी दूसरे कॉन्ट्रैक्ट को कॉल करना) करना। जब कोई कॉन्ट्रैक्ट Ether भेजता है या किसी बाहरी कॉन्ट्रैक्ट को कॉल करता है, तो यह अस्थायी रूप से एक्ज़ीक्यूशन कंट्रोल ट्रांसफर कर देता है। रिसीव करने वाले कॉन्ट्रैक्ट को नियंत्रित करने वाला अटैकर इसका फायदा उठा सकता है, वह तुरंत मूल कॉन्ट्रैक्ट में वापस कॉल करके ऐसा कर सकता है, अक्सर Ether ट्रांसफर से ट्रिगर होने वाले receive या fallback फंक्शन के माध्यम से, या टोकन स्टैंडर्ड हुक्स (hooks) के माध्यम से।
क्योंकि मूल कॉन्ट्रैक्ट की स्थिति (state) (जैसे, अटैकर का बैलेंस) अभी तक अपडेट नहीं हुई है, रीएंट्रेंट कॉल शुरुआती जांच (checks) पास कर लेती है, जिससे अटैकर एक ही ट्रांजैक्शन में कार्रवाई (जैसे फंड निकालना) को कई बार दोहरा सकता है। यह रिकर्सिव लूप तब तक जारी रहता है जब तक फंड खत्म नहीं हो जाते या गैस लिमिट तक नहीं पहुंच जाते।
हालांकि क्लासिक अटैक में एक ही फंक्शन शामिल होता है, इसके अधिक जटिल रूप मौजूद हैं, जैसे क्रॉस-फंक्शन रीएंट्रेंसी (फंक्शनों के बीच साझा स्थिति (shared state) का फायदा उठाना) और रीड-ओनली रीएंट्रेंसी (व्यू फंक्शन (view functions) के माध्यम से स्थिति (state) रीड को मैनिपुलेट करना)।
प्राथमिक बचाव चेक्स-इफेक्ट्स-इंटरेक्शन्स (Checks-Effects-Interactions - CEI) पैटर्न है: सभी आवश्यक जांच (checks) करें, फिर स्टेट वेरिएबल्स (effects - प्रभाव) को अपडेट करें, और इन अपडेट्स के बाद ही, बाहरी कॉन्ट्रैक्ट्स के साथ इंटरैक्ट करें।
भेद्यता "अनपेक्षित ईथर प्राप्ति के माध्यम से बैलेंस में हेरफेर" इसलिए उत्पन्न होती है क्योंकि सॉलिडिटी स्मार्ट कॉन्ट्रैक्ट्स उन तंत्रों के माध्यम से ईथर प्राप्त कर सकते हैं जो उनके परिभाषित `receive` और `fallback` फ़ंक्शन को बायपास करते हैं। इस "अनपेक्षित" ईथर इंजेक्शन के प्राथमिक तरीके `selfdestruct` ऑपकोड हैं, जो एक नष्ट हो रहे कॉन्ट्रैक्ट के बैलेंस को जबरन एक निर्दिष्ट पते पर स्थानांतरित करता है, और कॉइनबेस ट्रांज़ैक्शन (ब्लॉक रिवार्ड्स) हैं।
मूल मुद्दा यह है कि ये जबरन ट्रांसफर सीधे कॉन्ट्रैक्ट के ईथर बैलेंस (`address(this).balance`) को बढ़ाते हैं, बिना आने वाले फंड को संभालने के लिए कॉन्ट्रैक्ट के प्रोग्राम्ड लॉजिक को ट्रिगर किए। यह एक सामान्य, अक्सर निहित, धारणा या इनवेरिएंट को तोड़ता है: कि कॉन्ट्रैक्ट का वास्तविक बैलेंस उसके इच्छित `payable` फ़ंक्शन के माध्यम से संसाधित या आंतरिक रूप से हिसाब लगाए गए फंड के योग को सटीक रूप से दर्शाता है।
वे कॉन्ट्रैक्ट्स जो महत्वपूर्ण लॉजिक जाँच के लिए `address(this).balance` का गलत तरीके से उपयोग करते हैं, वे भेद्य हो जाते हैं। उदाहरण के लिए, कॉन्ट्रैक्ट्स यह जाँच सकते हैं कि `address(this).balance == अपेक्षित राशि`। एक हमलावर ईथर की थोड़ी मात्रा भेजने के लिए `selfdestruct` का उपयोग करके इसका फायदा उठा सकता है, जिससे बैलेंस में हेरफेर हो सकता है। यह निम्न का कारण बन सकता है:
डिनायल ऑफ सर्विस (DoS): सख्त समानता जाँच स्थायी रूप से बाधित हो सकती है, जिससे फ़ंक्शन अनुपयोगी हो जाते हैं।
लॉजिक मैनिपुलेशन: थ्रेशोल्ड समय से पहले पूरे हो सकते हैं, जिससे अनपेक्षित स्थिति परिवर्तन या भुगतान शुरू हो सकते हैं।
`assert` उल्लंघन: दुर्लभ मामलों में, अनपेक्षित बैलेंस आंतरिक स्थिति विसंगतियों का कारण बन सकता है जिससे `assert()` विफल हो जाता है, जिससे सभी ट्रांज़ैक्शन गैस का उपभोग होता है।
मौलिक शमन उपाय यह है कि कॉन्ट्रैक्ट लॉजिक के लिए कभी भी `address(this).balance` पर निर्भर न रहें। इसके बजाय, कॉन्ट्रैक्ट्स को समर्पित स्टेट वैरिएबल का उपयोग करके सटीक आंतरिक लेखांकन बनाए रखना चाहिए, उन्हें केवल वैध फंड-हैंडलिंग फ़ंक्शन के भीतर अपडेट करना चाहिए। सभी महत्वपूर्ण जाँच और स्थिति संक्रमण इन विश्वसनीय आंतरिक वैरिएबल पर आधारित होने चाहिए।
सॉलिडिटी स्मार्ट कॉन्ट्रैक्ट (Solidity smart contracts) में सेवा से इनकार (Denial of Service, DoS) कमजोरियाँ कॉन्ट्रैक्ट की इच्छित कार्यक्षमता को बाधित करने या पूरी तरह से रोकने का लक्ष्य रखती हैं, जिससे वैध उपयोगकर्ताओं को इसकी सेवाओं तक पहुँचने से रोका जा सके। जिस "सेवा" से इनकार किया जा रहा है, वह कॉन्ट्रैक्ट की अपने कार्यों को प्रोग्राम किए गए और उपयोगकर्ताओं द्वारा अपेक्षित रूप से निष्पादित करने की क्षमता है।
हमलावर इसे कॉन्ट्रैक्ट के कोड लॉजिक में खामियों का फायदा उठाकर, संसाधन सीमाओं (मुख्य रूप से गैस) में हेरफेर करके, या बाहरी निर्भरताओं का लाभ उठाकर हासिल करते हैं।
सामान्य पैटर्न में शामिल हैं:
गैस की समाप्ति (Gas Exhaustion): ऐसे लेनदेन बनाना या स्थिति (state) में हेरफेर करना जिससे फ़ंक्शन निष्पादन लागत ब्लॉक गैस सीमा या लेनदेन गैस सीमा से अधिक हो जाए। इसमें अक्सर कम्प्यूटेशनल रूप से महंगी ऑपरेशन्स को ट्रिगर करना या, बहुत सामान्य रूप से, असीमित Arrays पर पुनरावृति करना शामिल होता है जिनका आकार अनिश्चित काल तक बढ़ सकता है। जैसे-जैसे डेटा बढ़ता है, लूप की गैस लागत सीमा से अधिक हो जाती है, जिससे फ़ंक्शन अनुपयोगी हो जाता है।
अप्रत्याशित रिवर्ट्स (Unexpected Reverts): महत्वपूर्ण फ़ंक्शंस को अप्रत्याशित रूप से रिवर्ट (revert) करना। यह विफल बाहरी कॉल्स को मजबूर करके (उदाहरण के लिए, ऐसे कॉन्ट्रैक्ट को फंड भेजना जो उन्हें अस्वीकार करता है), `require` शर्तों को विफल करने के लिए स्थिति में हेरफेर करके, या अन्य अनियंत्रित अपवादों (exceptions) द्वारा ट्रिगर किया जा सकता है। यदि कोई कॉन्ट्रैक्ट एक बाहरी कॉल पर निर्भर करता है जो विफल हो जाता है (संभवतः दुर्भावनापूर्ण रूप से प्रेरित), तो पूरा ऑपरेशन अवरुद्ध हो सकता है।
स्मार्ट कॉन्ट्रैक्ट की अपरिवर्तनीय प्रकृति DoS को विशेष रूप से गंभीर बना देती है। एक सफल हमला स्थायी रूप से लॉक किए गए फंड या अप्राप्य कार्यक्षमता का कारण बन सकता है, क्योंकि कॉन्ट्रैक्ट कोड को परिनियोजन (post-deployment) के बाद आसानी से ठीक नहीं किया जा सकता है।
शमन सुरक्षित कोडिंग प्रथाओं पर निर्भर करता है: असीमित लूप्स के बजाय सीमित ऑपरेशन्स का उपयोग करना, उपयोगकर्ताओं को फंड "पुश" ("push-payment") करने के बजाय "पुल-पेमेंट" (उपयोगकर्ता द्वारा भुगतान खींचना) पैटर्न को प्राथमिकता देना, जो ट्रांसफर विफलताओं को अलग करता है, बाहरी कॉल विफलताओं को मजबूती से संभालना (उदाहरण के लिए, जहां उपयुक्त हो `try/catch` का उपयोग करना), और सावधानीपूर्वक गैस प्रबंधन।
इंटीजर ओवरफ़्लो (Integer overflow) और अंडरफ़्लो (integer underflow) की कमजोरियाँ स्मार्ट कॉन्ट्रैक्ट सुरक्षा के क्षेत्र में एक निरंतर खतरा हैं, जो निश्चित-आकार पूर्णांक अंकगणित (fixed-size integer arithmetic) की मौलिक सीमाओं से उत्पन्न होती हैं। ओवरफ़्लो तब होता है जब अंकगणितीय ऑपरेशन का परिणाम उसके प्रकार के अधिकतम मान से अधिक हो जाता है, और अंडरफ़्लो तब होता है जब परिणाम न्यूनतम मान से नीचे चला जाता है।
ऐतिहासिक रूप से, सॉलिडिटी (Solidity) के 0.8.0 से पहले के संस्करणों में, ये अंकगणितीय त्रुटियाँ मान को चुपचाप "रैप अराउंड" (wrap around) करने का कारण बनती थीं। उदाहरण के लिए, अधिकतम uint8 (255) में 1 जोड़ने पर 0 मिलता था, और 0 से 1 घटाने पर 255 मिलता था। यह पूर्वानुमानित लेकिन अनियंत्रित व्यवहार शोषण (exploit) का एक प्रमुख स्रोत था, जो हमलावरों को टोकन बैलेंस में हेरफेर करने (जैसे, भारी मात्रा में मिन्ट करना या बैलेंस को रैप अराउंड कराकर फंड निकालना), महत्वपूर्ण सुरक्षा जांचों को बायपास करने, कॉन्ट्रैक्ट की स्थिति को भ्रष्ट करने, या सेवा से इनकार (denial-of-service) का कारण बनने की अनुमति देता था।
सॉलिडिटी संस्करण 0.8.0 ने एक महत्वपूर्ण सुरक्षा वृद्धि पेश की: मानक अंकगणितीय संचालन (+, -, *, /) अब डिफ़ॉल्ट रूप से ओवरफ़्लो और अंडरफ़्लो जांच करते हैं। यदि कोई ऑपरेशन रैपिंग का परिणाम देता है, तो लेन-देन वापस (revert) हो जाता है, जिससे मूक स्थिति भ्रष्टाचार (silent state corruption) को रोका जा सके।
हालाँकि, जोखिम पूरी तरह से समाप्त नहीं हुआ है। डेवलपर्स अक्सर गैस अनुकूलन (gas optimization) के लिए `unchecked` ब्लॉक का उपयोग करके इन डिफ़ॉल्ट जांचों को स्पष्ट रूप से बायपास कर सकते हैं। `unchecked` ब्लॉक के भीतर का कोड 0.8.0-पूर्व संस्करणों के खतरनाक मूक रैपिंग व्यवहार पर वापस लौटता है और इसके लिए अत्यंत सावधानीपूर्वक सत्यापन (validation) की आवश्यकता होती है। इसी तरह, निम्न-स्तरीय EVM असेंबली कोड को सॉलिडिटी की जांच का लाभ नहीं मिलता है, जिसके लिए अंकगणितीय ऑपरेशनों के लिए मैन्युअल सुरक्षा प्रबंधन की आवश्यकता होती है। इसके अतिरिक्त, शिफ्ट ऑपरेशन (<<, >>) डिफ़ॉल्ट >=0.8.0 मोड में भी अनियंत्रित रहते हैं और परिणामों को छोटा (truncate) कर देंगे। अनुचित टाइप कास्टिंग (type casting) (उदाहरण के लिए, एक बड़े uint256 को uint8 जैसे छोटे प्रकार में परिवर्तित करना) भी मान को छोटा (value truncation) कर सकता है, जिससे संभावित रूप से बाद की गणनाओं में अप्रत्याशित व्यवहार हो सकता है।
इसलिए, यद्यपि आधुनिक सॉलिडिटी में डिफ़ॉल्ट रूप से काफी हद तक कम किया गया है, इंटीजर ओवरफ़्लो/अंडरफ़्लो अभी भी एक प्रासंगिक भेद्यता (relevant vulnerability) बनी हुई है, खासकर पुराने कॉन्ट्रैक्ट्स (legacy contracts) में, `unchecked` ब्लॉक या असेंबली का उपयोग करने वाले कोड में, और विशिष्ट अनियंत्रित ऑपरेशनों या लापरवाह प्रकार के रूपांतरणों के माध्यम से।
Solidity स्मार्ट कॉन्ट्रैक्ट्स में ऑथराइज़ेशन लॉजिक (authorization logic) के लिए `tx.origin` का उपयोग एक गंभीर सुरक्षा भेद्यता (security vulnerability) प्रस्तुत करता है। यह `msg.sender` की तुलना में इसके व्यवहार की मौलिक गलतफहमी से उत्पन्न होता है। जबकि `tx.origin` लगातार उस EOA (Externally Owned Account / बाहरी स्वामित्व वाला खाता) की पहचान करता है जिसने लेनदेन शुरू किया, `msg.sender` तत्काल कॉलर (immediate caller) की पहचान करता है। अनुमति जांच के लिए `tx.origin` का उपयोग करने से सीधे कॉन्ट्रैक्ट के साथ इंटरैक्ट करने वाली इकाई (entity) को मान्य करने में विफल रहता है।
यह खामी फ़िशिंग-शैली के हमलों (phishing-style attacks) का द्वार खोलती है, जहां एक दुर्भावनापूर्ण मध्यस्थ कॉन्ट्रैक्ट (intermediary contract), जिसे एक विशेषाधिकार प्राप्त उपयोगकर्ता द्वारा लागू (invoke) किया जाता है, लक्ष्य कॉन्ट्रैक्ट पर संरक्षित फ़ंक्शंस (protected functions) को सफलतापूर्वक कॉल कर सकता है। `tx.origin` जांच गलत तरीके से मूल उपयोगकर्ता को मान्य करती है, जिससे दुर्भावनापूर्ण कॉन्ट्रैक्ट उपयोगकर्ता के अधिकार (authority) के साथ कार्य निष्पादित कर सकता है। परिणाम Ether और टोकन की सीधी चोरी से लेकर कॉन्ट्रैक्ट स्थिति (contract state) के अनधिकृत हेरफेर तक होते हैं, जिससे संभावित रूप से महत्वपूर्ण वित्तीय नुकसान हो सकता है और प्रोटोकॉल की अखंडता (integrity) और प्रतिष्ठा (reputation) को अपूरणीय क्षति पहुँच सकती है।
अपर्याप्त एक्सेस नियंत्रण (Insufficient Access Control) सॉलिडिटी स्मार्ट कॉन्ट्रैक्ट्स में एक गंभीर भेद्यता है, जहाँ इस पर प्रतिबंध कि कौन कौन से फ़ंक्शन निष्पादित कर सकता है, या तो गायब होते हैं या अनुचित रूप से लागू किए जाते हैं। चूँकि सॉलिडिटी में अंतर्निहित अनुमति मॉडल का अभाव है, डेवलपर्स को मैन्युअल रूप से जाँच जोड़नी पड़ती है, अक्सर onlyOwner जैसे संशोधक (modifiers) का उपयोग करके या भूमिका-आधारित एक्सेस नियंत्रण (Role-Based Access Control - RBAC) को लागू करके। इसे सही ढंग से करने में विफलता सुरक्षा छेद (security holes) पैदा करती है।
यह भेद्यता आमतौर पर असुरक्षित फ़ंक्शन के रूप में प्रकट होती है। प्रशासनिक या संवेदनशील कार्यों के लिए बनाए गए फ़ंक्शन - जैसे अनुबंध स्वामित्व स्थानांतरित करना (changeOwner), धन निकालना (withdraw), अनुबंध को रोकना (pausing), टोकन बनाना (minting) या अनुबंध को नष्ट करना (selfdestruct) - किसी भी बाहरी खाते द्वारा कॉल करने योग्य छोड़े जा सकते हैं। यह अक्सर एक्सेस नियंत्रण संशोधकों के गायब होने या गलत फ़ंक्शन दृश्यता (visibility) (उदाहरण के लिए, यदि निर्दिष्ट नहीं है तो फ़ंक्शन डिफ़ॉल्ट रूप से public होते हैं) के कारण होता है। उजागर हुए इनिशियलाइज़ेशन फ़ंक्शन, जिन्हें केवल एक बार चलना चाहिए, यदि वे परिनियोजन (deployment) के बाद कॉल करने योग्य बने रहते हैं, तो वे भी हमले का एक ज़रिया (vector) हो सकते हैं, जो संभावित रूप से हमलावरों को स्वामित्व या महत्वपूर्ण पैरामीटर रीसेट करने की अनुमति देते हैं।
इसके परिणाम गंभीर होते हैं, जिनमें अनधिकृत उपयोगकर्ताओं द्वारा प्रशासनिक विशेषाधिकार प्राप्त करने से लेकर अनुबंध द्वारा प्रबंधित धन की पूरी चोरी या स्वयं अनुबंध का अपरिवर्तनीय विनाश शामिल है। वास्तविक दुनिया के एक्सप्लॉइट्स (Real-world exploits), जैसे पैरिटी वॉलेट (Parity Wallet) की घटनाएं और LAND टोकन हैक, अपर्याप्त एक्सेस नियंत्रण की विनाशकारी क्षमता को दर्शाते हैं।
शमन (Mitigation) में सभी संवेदनशील फ़ंक्शन पर एक्सेस नियंत्रण जाँचों को सख्ती से लागू करना, न्यूनतम विशेषाधिकार के सिद्धांत (Principle of Least Privilege) का पालन करना, Ownable या RBAC जैसे स्थापित पैटर्न का उपयोग करना (अक्सर OpenZeppelin जैसी लाइब्रेरी के माध्यम से), और पूरी तरह से परीक्षण और ऑडिट करना शामिल है।
एथेरियम वर्चुअल मशीन (EVM) पर सुरक्षित यादृच्छिकता (randomness) उत्पन्न करना चुनौतीपूर्ण है, क्योंकि इसकी नियतात्मक (deterministic) प्रकृति नेटवर्क सर्वसम्मति के लिए आवश्यक है। यह एक "एन्ट्रॉपी भ्रम" पैदा करता है जहाँ पूरी तरह से ऑन-चेन डेटा से प्राप्त प्रतीत होने वाले यादृच्छिक मान वास्तव में पूर्वानुमान योग्य होते हैं।
डेवलपर अक्सर आसानी से उपलब्ध ब्लॉक वेरिएबल जैसे block.timestamp, blockhash, और पोस्ट-मर्ज prevrandao (block.difficulty के माध्यम से एक्सेस किया गया) का छद्म-यादृच्छिकता (pseudo-randomness) के स्रोतों के रूप में दुरुपयोग करते हैं। ये वेरिएबल असुरक्षित हैं क्योंकि इनका अनुमान लगाया जा सकता है या इन्हें प्रभावित किया जा सकता है।
माइनर (प्रूफ-ऑफ-वर्क में) या वैलिडेटर (प्रूफ-ऑफ-स्टेक में) अनुचित लाभ प्राप्त करने के लिए इन मानों में कुछ हद तक हेरफेर कर सकते हैं, अक्सर MEV (अधिकतम निकालने योग्य मूल्य) रणनीतियों के हिस्से के रूप में। महत्वपूर्ण रूप से, यदि यादृच्छिकता तर्क केवल लेनदेन निष्पादन से पहले या उसके दौरान ज्ञात इनपुट पर निर्भर करता है, तो नियमित उपयोगकर्ता या हमलावर अनुबंध भी अक्सर परिणामों का अनुमान लगा सकते हैं, जिससे फ्रंट-रनिंग जैसे कारनामों को अंजाम दिया जा सकता है। यह पूर्वानुमानशीलता लॉटरी, गेम और एनएफटी मिंट जैसे अनुप्रयोगों की निष्पक्षता को कमजोर करती है।
कई डायनामिक प्रकारों के साथ `abi.encodePacked` के माध्यम से हैश टकराव (Hash Collision) अंतर्निहित Keccak-256 हैश फ़ंक्शन की कमजोरियों से उत्पन्न नहीं होता है, बल्कि डेटा को हैश करने से पहले एन्कोड करने के तरीके से होता है, विशेष रूप से सॉलिडिटी के `abi.encodePacked` फ़ंक्शन का उपयोग करते समय। मानक `abi.encode` के विपरीत, जो तर्कों को 32 बाइट्स तक पैडिंग करता है और डायनामिक प्रकारों के लिए लंबाई उपसर्ग (length prefixes) शामिल करता है, `abi.encodePacked` आवश्यक न्यूनतम बाइट्स का उपयोग करके तर्कों को जोड़कर एक कॉम्पैक्ट, गैर-मानक एन्कोडिंग बनाता है, छोटे स्थिर प्रकारों के लिए पैडिंग को छोड़ देता है और, महत्वपूर्ण रूप से, `string`, `bytes`, या डायनामिक ऐरे जैसे डायनामिक प्रकारों के लिए लंबाई की जानकारी को छोड़ देता है।
मुख्य समस्या तब होती है जब `abi.encodePacked` का उपयोग दो या दो से अधिक आसन्न डायनामिक-प्रकार के तर्कों के साथ किया जाता है। क्योंकि प्रत्येक डायनामिक तर्क की लंबाई एन्कोड नहीं की जाती है, परिणामी बाइट स्ट्रिंग में उनके बीच की सीमा अस्पष्ट हो जाती है। यह अस्पष्टता अक्सर तुच्छ रूप से, तार्किक इनपुट के विभिन्न सेटों को तैयार करना संभव बनाती है जो बिल्कुल समान पैक्ड बाइट अनुक्रम उत्पन्न करते हैं। उदाहरण के लिए, `abi.encodePacked("a", "bc")` वही बाइट आउटपुट देता है जो `abi.encodePacked("ab", "c")` देता है।
जब यह समान बाइट आउटपुट बाद में हैश किया जाता है (उदाहरण के लिए, `keccak256(abi.encodePacked(...))`), तो इसका परिणाम समान हैश मान होता है, जो एन्कोडिंग-प्रेरित हैश टकराव है।
यदि परिणामी हैश का उपयोग सुरक्षा-संवेदनशील संदर्भ में किया जाता है, तो इस एन्कोडिंग टकराव भेद्यता का कई तरीकों से फायदा उठाया जा सकता है:
हस्ताक्षर सत्यापन बाईपास (Signature Verification Bypass): एक हमलावर मापदंडों के एक सेट के लिए बनाए गए वैध हस्ताक्षर को ले सकता है और इसे मापदंडों के एक अलग, दुर्भावनापूर्ण सेट के साथ पुन: उपयोग कर सकता है जो एक टकराने वाला हैश उत्पन्न करता है। अनुबंध का हस्ताक्षर सत्यापन (`ecrecover`) सफल होगा, जिससे अनधिकृत निष्पादन की अनुमति मिल जाएगी।
मैपिंग कुंजी टकराव के माध्यम से स्थिति भ्रष्टाचार (State Corruption via Mapping Key Collisions): यदि टकराव-प्रवण हैश का उपयोग मैपिंग (`mapping(bytes32 => ...)`) में कुंजी के रूप में किया जाता है, तो एक हमलावर एक वैध उपयोगकर्ता की कुंजी से टकराने वाली कुंजी उत्पन्न करने के लिए इनपुट तैयार कर सकता है, संभावित रूप से उनके डेटा को अधिलेखित कर सकता है, एक्सेस नियंत्रणों को दरकिनार कर सकता है, या सेवा से इनकार (Denial of Service) का कारण बन सकता है।
संदेश प्रमाणीकरण मुद्दे (Message Authentication Issues): भेद्यता उन जांचों को कमजोर करती है जो डेटा अखंडता सुनिश्चित करने के लिए हैश पर निर्भर करती हैं, क्योंकि अलग-अलग तार्किक संदेश हैशिंग के बाद समान दिखाई दे सकते हैं।
सफल शोषण के परिणाम गंभीर हो सकते हैं, जिनमें कार्यों या डेटा तक अनधिकृत पहुंच, प्रत्यक्ष निधि चोरी (Fund Theft), महत्वपूर्ण स्थिति भ्रष्टाचार (Critical State Corruption), और सेवा से इनकार (Denial of Service - DoS) शामिल हैं।
सटीकता हानि की कमजोरियां पूर्णांक अंकगणित पर निर्भरता और फ्लोटिंग-पॉइंट नंबरों के लिए मूल समर्थन की कमी से उत्पन्न होती हैं। यह डिज़ाइन नियतात्मक निष्पादन को प्राथमिकता देता है लेकिन डेवलपर्स को मैन्युअल रूप से भिन्नात्मक मानों का प्रबंधन करने की आवश्यकता होती है, जिससे त्रुटियों के अवसर पैदा होते हैं।
मूल मुद्दा पूर्णांक विभाजन छोटा करना है: सॉलिडिटी शेषफलों को छोड़ देता है और विभाजन परिणामों को शून्य की ओर पूर्णांकित करता है। इस पूर्वानुमेय व्यवहार का शोषण किया जा सकता है, अक्सर जैसे पैटर्न के माध्यम से:
गुणा से पहले भाग: (a * c) / b के बजाय (a / b) * c की गणना मध्यवर्ती परिणाम a / b को छोटा कर देती है, जिससे सटीकता हानि बढ़ जाती है।
शून्य की ओर नीचे पूर्णांकन: यदि अंश A हर B से कम है (और दोनों सकारात्मक हैं), तो A / B का परिणाम हमेशा 0 होता है। यह छोटी फीस, पुरस्कार, या टोकन रूपांतरणों से जुड़े गणनाओं के लिए जोखिम भरा है।
हमलावर वित्तीय लाभ के लिए अनुबंध तर्क में हेरफेर करने के लिए इन गणितीय गुणों का फायदा उठाते हैं। सामान्य रणनीतियों में शामिल हैं:
स्थिति/मूल्य में हेरफेर: विनिमय दरों, पूल भंडार, वॉल्ट शेयर कीमतों, या संपार्श्विक अनुपात जैसे महत्वपूर्ण प्रोटोकॉल मानों को विकृत करने के लिए राउंडिंग त्रुटियों को ट्रिगर करना, जिनका बाद के लेनदेन में फायदा उठाया जा सकता है।
किनारे के मामलों को लक्षित करना: बहुत छोटे इनपुट वाले लेनदेन या बड़े आंतरिक मानों के साथ बातचीत करने के लिए डिज़ाइन किए गए इनपुट का उपयोग करके ट्रंकेशन के प्रभाव को अधिकतम करना, जिससे अक्सर गणना शून्य हो जाती है।
सफल सटीकता हानि हमलों से महत्वपूर्ण नकारात्मक परिणाम हो सकते हैं:
कम लागत: हमलावर कम या शून्य शुल्क/लागत का भुगतान करते हैं।
बढ़े हुए लाभ: हमलावर अवैध रूप से अधिक टोकन, शेयर या पुरस्कार प्राप्त करते हैं।
मध्यस्थता के अवसर: हमलावरों के शोषण के लिए प्रोटोकॉल के भीतर कृत्रिम मूल्य अंतर पैदा करना।
जोखिम तंत्रों को दरकिनार करना: गलत गणनाओं के कारण परिसमापन या अन्य सुरक्षा जांचों को बायपास करना।
धीरे-धीरे फंड की कमी: छोटी राउंडिंग त्रुटियों ("1 wei हमले") का फायदा उठाकर बार-बार लेनदेन के माध्यम से मूल्य निकालना।
शमन में सावधानीपूर्वक अंकगणितीय हैंडलिंग शामिल है, जैसे कि विभाजन से पहले गुणन करना, संख्यात्मक स्केलिंग का उपयोग करना (फिक्स्ड-पॉइंट मैथ का अनुकरण करना), विशेष गणित पुस्तकालयों को नियोजित करना, और उपयुक्त राउंडिंग लॉजिक लागू करना। मानक ओवरफ्लो जांच (जैसे SafeMath या Solidity >=0.8) विभाजन से सटीकता हानि को नहीं रोकते हैं।
यह भेद्यता (vulnerability) तब होती है जब कोई स्मार्ट कॉन्ट्रैक्ट लूप के भीतर msg.value का अनुचित तरीके से उपयोग करता है। मूल समस्या इस तथ्य से उत्पन्न होती है कि msg.value लेनदेन के पूरे निष्पादन संदर्भ (execution context) में स्थिर रहता है। यदि कोई लूप कई बार पुनरावृत्ति (iterate) करता है, और प्रत्येक पुनरावृत्ति में इस प्रारंभिक msg.value के आधार पर जांच या क्रियाएं करता है, बिना उन पुनरावृत्तियों में संसाधित या खर्च किए गए संचयी मूल्य को सही ढंग से ट्रैक किए, तो यह शोषण (exploit) का अवसर पैदा करता है।
एक हमलावर भेद्य फ़ंक्शन को ट्रिगर करने के लिए ईथर (Ether) की एक विशिष्ट राशि भेजकर इसका फायदा उठा सकता है। लूप के अंदर, require(msg.value >= amount_per_item) जैसी जांचें बार-बार पास हो सकती हैं, या स्थिति अपडेट गलत तरीके से पूरे प्रारंभिक msg.value का कई बार उपयोग कर सकते हैं। ऐसा इसलिए होता है क्योंकि कॉन्ट्रैक्ट लॉजिक उसी लूप के पिछले पुनरावृत्तियों में प्रभावी ढंग से 'खर्च' या आवंटित किए गए मूल्य का हिसाब रखने में विफल रहता है।
यह खामी एक हमलावर को ऐसी क्रियाएं ट्रिगर करने की अनुमति देती है (जैसे ईथर ट्रांसफर या आंतरिक बैलेंस क्रेडिट) जिनका कुल मूल्य लेनदेन के साथ वास्तव में भेजे गए ईथर से काफी अधिक होता है।
ecrecover एक आवश्यक EVM प्रीकंपाइल है जो स्मार्ट कॉन्ट्रैक्ट्स को संदेश हैश और ECDSA हस्ताक्षर (v, r, s) से हस्ताक्षरकर्ता का पता पुनर्प्राप्त करने की अनुमति देता है। यह महत्वपूर्ण कार्यक्षमताओं को सक्षम बनाता है, जैसे मेटा-ट्रांजैक्शन (meta-transactions) या परमिट फ़ंक्शंस (permit functions) के लिए ऑफ-चेन हस्ताक्षरित संदेशों का सत्यापन करना। हालाँकि, यदि इसे सावधानी से नहीं संभाला जाता है, तो इसका सीधा उपयोग महत्वपूर्ण, अक्सर कम आंका जाने वाला, सुरक्षा जोखिम प्रस्तुत करता है।
शून्य-पता वापसी भेद्यता (Zero-Address Return Vulnerability): एक महत्वपूर्ण मुद्दा `ecrecover` की अद्वितीय त्रुटि हैंडलिंग से उत्पन्न होता है। जब अमान्य या गणितीय रूप से असंभव हस्ताक्षर प्रस्तुत किया जाता है, तो यह लेनदेन को रिवर्ट नहीं करता है। इसके बजाय, यह चुपचाप विफल हो जाता है और शून्य पता (`address(0)`) लौटाता है। जो कॉन्ट्रैक्ट `ecrecover` को कॉल करते हैं लेकिन शून्य-पता जांच की कमी से ग्रस्त हैं, वे अत्यधिक असुरक्षित होते हैं। एक हमलावर जानबूझकर अमान्य हस्ताक्षर डेटा जमा कर सकता है, जिससे `ecrecover` `address(0)` लौटाएगा। यदि इस आउटपुट को स्पष्ट रूप से जांचा और अस्वीकार नहीं किया जाता है, तो कॉन्ट्रैक्ट गलत तरीके से आगे बढ़ सकता है और `address(0)` को वैध हस्ताक्षरकर्ता मान सकता है। इससे गंभीर परिणाम हो सकते हैं, जैसे अनधिकृत स्थिति परिवर्तन, गलत इवेंट उत्सर्जन, या अनुमतियाँ प्रदान करना, खासकर यदि शून्य पते के पास कॉन्ट्रैक्ट के विशिष्ट तर्क के भीतर विशेष विशेषाधिकार या सार्थक स्थिति है। मजबूत कोड को हमेशा `ecrecover` कॉल के तुरंत बाद `recoveredAddress != address(0)` को मान्य करना चाहिए।
हस्ताक्षर लचीलापन भेद्यता (Signature Malleability Vulnerability): दूसरा बड़ा जोखिम ECDSA एल्गोरिथम की एक अंतर्निहित संपत्ति से उत्पन्न होता है: हस्ताक्षर लचीलापन (signature malleability)। किसी दिए गए संदेश और निजी कुंजी के लिए, कई अलग-अलग लेकिन क्रिप्टोग्राफ़िक रूप से मान्य हस्ताक्षर प्रतिनिधित्व मौजूद हो सकते हैं (विशेष रूप से, घटक `s` का उपयोग करने वाले हस्ताक्षर को अक्सर `n-s` का उपयोग करके एक मान्य हस्ताक्षर में बदला जा सकता है, जहां `n` वक्र का क्रम है)। यह एक भेद्यता बन जाती है यदि कॉन्ट्रैक्ट गलत तरीके से मानते हैं कि किसी संदेश के लिए हस्ताक्षर अद्वितीय है। हमलावर विशिष्टता जांचों को बायपास करके इसका फायदा उठा सकते हैं। उदाहरण के लिए, यदि कोई कॉन्ट्रैक्ट रीप्ले को रोकने के लिए हस्ताक्षर के हैश को ही नॉन्स (nonce) के रूप में उपयोग करता है (एक त्रुटिपूर्ण पैटर्न), तो हमलावर एक मान्य हस्ताक्षर ले सकता है, उसके लचीले समकक्ष की गणना कर सकता है, और कार्रवाई को फिर से निष्पादित करने के लिए उसे जमा कर सकता है, क्योंकि हस्ताक्षर हैश अलग-अलग होंगे। यह उन सिस्टम में अप्रत्याशित व्यवहार या रीप्ले का कारण भी बन सकता है जो विशिष्ट हस्ताक्षर रूप की अपेक्षा करते हैं, यदि बाहरी सिस्टम या कॉन्ट्रैक्ट तर्क के हिस्से दोनों मान्य हस्ताक्षर रूपों को संभालने के लिए डिज़ाइन नहीं किए गए थे। प्रभावी शमन में हस्ताक्षर मानकीकरण (signature canonicalization) लागू करना शामिल है – यह OpenZeppelin के ECDSA जैसी मानक पुस्तकालयों में मजबूती से लागू की गई एक जाँच है, जिसे सीधे `ecrecover` उपयोग पर प्राथमिकता दी जानी चाहिए।
क्रॉस-चेन रीप्ले अटैक (CCRA): एक EVM चेन पर वैध रूप से निष्पादित लेनदेन (transaction) को कैप्चर किया जाता है और एक अलग EVM चेन पर सफलतापूर्वक पुनः सबमिट कर दिया जाता है। यह चेनों के बीच लेनदेन प्रारूपों और हस्ताक्षरों (signatures) में समानताओं का फायदा उठाता है, खासकर जब लेनदेन में अद्वितीय चेन पहचानकर्ता (Chain ID) की कमी होती है। इथेरियम/इथेरियम क्लासिक हार्ड फोर्क (hard fork) एक क्लासिक उदाहरण है जहाँ यह जोखिम सामने आया। EIP-155 को मानक लेनदेन हस्ताक्षरों में चेन आईडी को एम्बेड करके इसे कम करने के लिए पेश किया गया था, जिससे वे चेन-विशिष्ट बन गए। हालाँकि, कस्टम हस्ताक्षर सत्यापन (custom signature verification) का उपयोग करने वाले स्मार्ट कॉन्ट्रैक्ट (smart contracts) को भी स्पष्ट रूप से चेन आईडी की जाँच करनी चाहिए। विंटरम्यूट के खिलाफ $20 मिलियन का ऑप्टिमिज्म एक्सप्लॉइट (exploit) एक क्रॉस-चेन पर तैनात कॉन्ट्रैक्ट में ऐसी ही गायब चेन आईडी जाँच के कारण हुआ था।
स्मार्ट कॉन्ट्रैक्ट-स्तरीय रीप्ले (एक ही चेन): एक हस्ताक्षरित संदेश (signed message) या लेनदेन को उसी स्मार्ट कॉन्ट्रैक्ट, या संभावित रूप से उसी चेन पर किसी अन्य कॉन्ट्रैक्ट के खिलाफ रीप्ले किया जाता है। यह आमतौर पर कॉन्ट्रैक्ट के स्वयं के लॉजिक के भीतर कमजोरियों (vulnerabilities) का फायदा उठाता है, खासकर मेटा-ट्रांजेक्शन (meta-transactions) या ERC-20 परमिट (permit) फ़ंक्शंस जैसी सुविधाओं के लिए उपयोग किए जाने वाले कस्टम हस्ताक्षर सत्यापन योजनाओं में। सबसे आम खामी एप्लिकेशन-स्तरीय नॉन्स (nonce) की अनुपस्थिति या अनुचित कार्यान्वयन है। नॉन्स («एक बार इस्तेमाल किया गया नंबर») हस्ताक्षरकर्ता (signer) से जुड़ा एक अद्वितीय काउंटर है जिसे हस्ताक्षरित संदेश डाइजेस्ट (signed message digest) में शामिल किया जाना चाहिए और कॉन्ट्रैक्ट द्वारा ऑन-चेन (on-chain) ट्रैक किया जाना चाहिए ताकि यह सुनिश्चित हो सके कि प्रत्येक विशिष्ट हस्ताक्षर केवल एक क्रिया को अधिकृत करता है।
सॉलिडिटी का मल्टीपल इनहेरिटेंस के लिए समर्थन एक अनुबंध को एक साथ कई पैरेंट अनुबंधों से सुविधाओं को इनहेरिट करने की अनुमति देता है। कोड के पुन: उपयोग के लिए शक्तिशाली होते हुए भी, यह संभावित अस्पष्टता का परिचय देता है, जिसे "डायमंड प्रॉब्लम" के रूप में जाना जाता है: यदि दो या दो से अधिक बेस अनुबंध समान नाम और पैरामीटर वाले फ़ंक्शन को परिभाषित करते हैं।
इसे हल करने के लिए, सॉलिडिटी प्रत्येक अनुबंध के लिए एकल, नियतात्मक मेथड रेजोल्यूशन ऑर्डर (MRO) स्थापित करने के लिए C3 लीनियराइज़ेशन एल्गोरिथम का उपयोग करता है। यह MRO उस सटीक अनुक्रम को निर्देशित करता है जिसमें फ़ंक्शन कॉल को हल करते समय बेस अनुबंधों की जाँच की जाती है।
भेद्यता सीधे तौर पर इस बात से उत्पन्न होती है कि यह MRO कैसे निर्धारित होता है। महत्वपूर्ण कारक वह क्रम है जिसमें डेवलपर `is` स्टेटमेंट में बेस अनुबंधों को सूचीबद्ध करता है। सॉलिडिटी को "सबसे बेस-जैसे" से "सबसे व्युत्पन्न" तक अनुबंधों को सूचीबद्ध करने की आवश्यकता होती है। यह निर्दिष्ट क्रम सीधे C3 एल्गोरिथम द्वारा उत्पन्न अंतिम MRO को प्रभावित करता है।
भेद्यता तब होती है जब डेवलपर एक इनहेरिटेंस क्रम प्रदान करता है जो इच्छित तार्किक पदानुक्रम या प्राथमिकता से मेल नहीं खाता है। यदि किसी अधिक सामान्य अनुबंध को अधिक विशिष्ट अनुबंध के बाद सूचीबद्ध किया जाता है, या क्रम अन्यथा MRO को अनपेक्षित फ़ंक्शन कार्यान्वयन को प्राथमिकता देने का कारण बनता है, तो अनुबंध अप्रत्याशित रूप से व्यवहार कर सकता है। उदाहरण के लिए, एक कॉल एक बेस फ़ंक्शन पर हल हो सकती है जिसमें महत्वपूर्ण सुरक्षा जाँच या अद्यतन लॉजिक की कमी होती है जिसे एक इच्छित, लेकिन गलत क्रम में, व्युत्पन्न अनुबंध ओवरराइड में लागू किया गया था।
गलत इनहेरिटेंस क्रम के कारण गलत फ़ंक्शन निष्पादित करने के परिणामों में एक्सेस नियंत्रणों को दरकिनार करना, पुरानी या गलत व्यावसायिक लॉजिक निष्पादित करना, स्टेट करप्शन और संभावित वित्तीय हानि शामिल हैं। अनिवार्य रूप से, अनुबंध का वास्तविक निष्पादन प्रवाह डेवलपर के डिज़ाइन से विचलित होता है, जिससे सुरक्षा और कार्यक्षमता कमजोर होती है।
अधिकतम निष्कर्षण योग्य मूल्य (Maximal Extractable Value - MEV) उस लाभ का प्रतिनिधित्व करता है जिसे ब्लॉक उत्पादक और विशेष खोजकर्ता (searchers) मानक ब्लॉक पुरस्कार और गैस शुल्क के अलावा, एक ब्लॉक के भीतर लेनदेन के समावेशन और क्रम में हेरफेर करके प्राप्त कर सकते हैं। मूल रूप से इसे "माइनर निष्कर्षण योग्य मूल्य" (Miner Extractable Value) कहा जाता था, बाद में इनाम के प्रति लालच को दर्शाने के लिए नाम बदलकर "अधिकतम" कर दिया गया।
MEV इसलिए उत्पन्न होता है क्योंकि लंबित लेनदेन अक्सर मेमपूल (mempool) नामक एक सार्वजनिक प्रतीक्षा क्षेत्र में होते हैं, जो किसी के लिए भी दृश्यमान होता है। ब्लॉक उत्पादकों के पास एक ब्लॉक में लेनदेन के अंतिम क्रम को तय करने का अधिकार होता है। "खोजकर्ताओं" (searchers) द्वारा चलाए जाने वाले स्वचालित बॉट लगातार मेमपूल की निगरानी करते हैं, संभावित परिणामों का अनुकरण करते हैं, और रणनीतिक रूप से लेनदेन को क्रमबद्ध करके लाभदायक अवसरों का फायदा उठाते हैं, अक्सर पसंदीदा स्थान सुनिश्चित करने के लिए गैस बोली (प्राथमिकता गैस नीलामी - PGA) का उपयोग करते हैं।
सामान्य MEV रणनीतियाँ, जिन्हें अक्सर हमले के रूप में देखा जाता है, उनमें शामिल हैं:
फ्रंट-रनिंग (Front-Running): अपेक्षित मूल्य प्रभाव से लाभ उठाने के लिए हमलावर के लेनदेन को पीड़ित के लेनदेन (जैसे, एक बड़ा DEX व्यापार) से पहले रखना।
सैंडविच अटैक (Sandwich Attacks): हेरफेर के कारण हुए मूल्य अंतर (स्लिपेज) को पकड़ने के लिए पीड़ित के DEX व्यापार को फ्रंट-रनिंग और बैक-रनिंग (पीछे चलना) का संयोजन।
ऐन वक्त पर तरलता (JIT Liquidity): शुल्क प्राप्त करने के लिए केंद्रित तरलता DEX पर एक बड़े स्वैप के आसपास अस्थायी रूप से तरलता जोड़ना और हटाना।
ओरेकल हेरफेर (Oracle Manipulation): लाभ के लिए मूल्य ओरेकल अपडेट या अशुद्धियों का फायदा उठाना, जो अक्सर उधार प्रोटोकॉल को प्रभावित करता है।
अन्य प्रकारों में NFT स्निपिंग और डस्ट अटैक (धूल हमला) शामिल हैं।
उपयोगकर्ताओं के लिए परिणामों में गैस युद्धों के कारण बढ़ी हुई लेनदेन लागत, ट्रेडों पर खराब निष्पादन मूल्य (स्लिपेज), तरलता प्रदाताओं के लिए बढ़ा हुआ अस्थायी नुकसान (impermanent loss), और अनुचित रूप से शुरू किए गए परिसमापन (liquidations) शामिल हैं।
शमन रणनीतियों का उद्देश्य MEV के नकारात्मक प्रभाव को कम करना है। निजी मेमपूल या रिले (जैसे Flashbots Protect, या MEV Blocker) के माध्यम से लेनदेन भेजने से वे सार्वजनिक दृश्य से छिप जाते हैं। कमिट-रिवील (Commit-Reveal) योजनाओं जैसे एप्लिकेशन-स्तरीय डिज़ाइन लेनदेन के विवरण को तब तक अस्पष्ट करते हैं जब तक कि ऑर्डरिंग तय नहीं हो जाती, जबकि ओरेकल के लिए समय-भारित औसत मूल्य (TWAP) का उपयोग करने से हेरफेर के जोखिम कम हो सकते हैं।