
ecdsa (PyPI) में डिनायल ऑफ सर्विस भेद्यता
ecdsa (PyPI) में सेवा अस्वीकार भेद्यता
मैंने python-ecdsa में मध्यम-गंभीरता की भेद्यता की पहचान की और जिम्मेदारीपूर्वक इसका खुलासा किया। यह पायथन क्रिप्टोग्राफी लाइब्रेरी व्यापक रूप से उपयोग की जाती है, पिछले महीने 47.8M डाउनलोड हुए।
मुझे यह मुद्दा python-ecdsa की समीक्षा करते समय एक बहुत ही विशिष्ट प्रश्न को ध्यान में रखते हुए मिला:
क्या होता है अगर दुर्भावनापूर्ण DER इसकी लंबाई के बारे में झूठ बोलता है और पार्सर इस पर बहुत अधिक भरोसा करता है?
इस मामले में, उस प्रश्न ने एक वास्तविक बग की ओर अग्रसर किया।
ecdsa.der में DER पार्सिंग सहायकों ने उन मामलों में छोटा किया गया डेटा स्वीकार किया जहां एन्कोडेड लंबाई वास्तव में उपलब्ध बाइट्स से अधिक होने का दावा करती थी। उस दुर्भावनापूर्ण इनपुट को तुरंत अस्वीकार कर दिया जाना चाहिए था। इसके बजाय, यह पार्सिंग लॉजिक में गहराई तक जा सकता था और अंततः कुंजी पार्सिंग के दौरान एक आंतरिक IndexError को ट्रिगर कर सकता था।
यह मुद्दा CVE-2026-33936 बन गया।
प्रोजेक्ट: GitHub पर python-ecdsa
पैकेज: ecdsa (pip)
CVE: CVE-2026-33936
हमलावर-नियंत्रित दुर्भावनापूर्ण DER → छोटी लंबाई को मान्य मानकर स्वीकार किया गया → पार्सर विश्वास सीमा से आगे बढ़ता है → SigningKey.from_der() आंतरिक अपवाद पथ तक पहुंचता है → अप्रत्याशित IndexError / एप्लिकेशन-स्तरीय DoS जोखिम
python-ecdsa अण्डाकार वक्र क्रिप्टोग्राफी के लिए व्यापक रूप से उपयोग की जाने वाली पायथन लाइब्रेरी है।
अन्य चीजों के अलावा, यह संभालता है:
इसका मतलब है कि इसका पार्सिंग कोड सीधे सुरक्षा सीमा पर स्थित है।
जब भी कोई लाइब्रेरी बाहरी रूप से आपूर्ति की गई कुंजी सामग्री या संरचित बाइनरी इनपुट स्वीकार करती है, सहीता केवल गुणवत्ता का मुद्दा नहीं है। यह एक सुरक्षा गुण है।
यदि दुर्भावनापूर्ण इनपुट को अस्वीकार किए जाने पर स्वीकार किया जाता है, तो डाउनस्ट्रीम कोड अमान्य स्थिति के शीर्ष पर धारणाएं बनाना शुरू कर देता है। यहीं पर बग "सिर्फ पार्सिंग गलतियाँ" होना बंद कर देते हैं और भेद्यता बनने लगते हैं।
DER पार्सिंग उन क्षेत्रों में से एक है जहां छोटी सत्यापन गलतियों का अत्यधिक प्रभाव हो सकता है।
बग वर्ग सीधा है:
सुरक्षा समीक्षा में देखने लायक बिल्कुल उस तरह की सीमा विफलता है।
मैं यहां अजीब क्रिप्टोग्राफिक व्यवहार की तलाश नहीं कर रहा था। मैं संरचित-इनपुट हैंडलिंग में विश्वास विफलताओं की तलाश कर रहा था।
वह देखने के लिए सही जगह थी।
मूल मुद्दा दुर्भावनापूर्ण या छोटे इनपुट को पार्स करते समय DER लंबाई फील्ड का अनुचित सत्यापन था।
विशेष रूप से, ecdsa.der.remove_octet_string() ने ऐसे इनपुट को स्वीकार किया जहां घोषित DER लंबाई बफर में वास्तव में उपलब्ध बाइट्स की संख्या से अधिक थी।
इसलिए इस तरह के दुर्भावनापूर्ण DER को अस्वीकार करने के बजाय:
40963सहायक ने इसे स्वीकार कर लिया और छोटी सामग्री को मान्य मानकर लौटा दिया।
वह पहले से ही एक बग है।
लेकिन मजबूत प्रभाव डाउनस्ट्रीम में दिखा।
क्योंकि दुर्भावनापूर्ण इनपुट को सीमा पर अस्वीकार करने के बजाय स्वीकार कर लिया गया, SigningKey.from_der() बाद में एक आंतरिक अपवाद पथ तक पहुंच सकता था और उठा सकता था:
IndexError: index out of bounds on dimension 1
यह मायने रखता है क्योंकि यह उस तरह की विफलता नहीं है जिसकी कॉलर दुर्भावनापूर्ण इनपुट से उम्मीद करता है।
सही व्यवहार एक साफ पार्स अस्वीकृति है जैसे UnexpectedDER या ValueError।
इसलिए भेद्यता केवल "IndexError मौजूद है" नहीं थी।
असली भेद्यता यह थी:
यह एक बग श्रृंखला है, दो असंबंधित मुद्दे नहीं।
एक पार्सर द्वारा दुर्भावनापूर्ण इनपुट को अस्वीकार करना एक कॉस्मेटिक सुधार नहीं है। यह सुरक्षा मॉडल का हिस्सा है।
यहां महत्वपूर्ण अंतर यह नहीं है कि इनपुट अमान्य था या नहीं। बेशक यह अमान्य था।
महत्वपूर्ण अंतर यह है कि लाइब्रेरी ने अमान्य इनपुट के सामने कैसे व्यवहार किया।
इनके बीच एक वास्तविक अंतर है:
पहला मजबूत व्यवहार है।
दूसरा एप्लिकेशन-स्तरीय जोखिम पैदा करता है यदि सॉफ्टवेयर अविश्वसनीय DER को पार्स करता है और मान लेता है कि लाइब्रेरी विफलताएं अपेक्षित अपवाद प्रकारों के भीतर रहती हैं।
यही कारण है कि इसे केवल पार्सर-गुणवत्ता बग के बजाय एक भेद्यता के रूप में उचित रूप से वर्गीकृत किया गया था।
मैंने दो PoCs का उपयोग किया क्योंकि उन्होंने एक ही बग श्रृंखला के दो अलग-अलग हिस्सों का प्रदर्शन किया।
पहले PoC ने दिखाया कि remove_octet_string() ने छोटे DER को स्वीकार किया जिसकी घोषित लंबाई उपलब्ध बफर से अधिक थी।
इसने मुख्य सत्यापन विफलता स्थापित की:
दूसरे PoC ने अधिक महत्वपूर्ण डाउनस्ट्रीम प्रभाव दिखाया:
SigningKey.from_der() को दिया गया दुर्भावनापूर्ण DER नियतात्मक रूप से फिक्स से पहले एक आंतरिक IndexError को ट्रिगर करता था।
इसने सुरक्षा-प्रासंगिक प्रभाव स्थापित किया:
यह "पार्सर ने अजीब बाइट्स स्वीकार किए" से कहीं अधिक मजबूत परिणाम है।
यह सीमा विफलता और वास्तविक परिचालन परिणाम दोनों दिखाता है।
पहला PoC मूल कारण साबित करता है।
दूसरा PoC प्रभाव साबित करता है।
वह विभाजन मायने रखता है।
बहुत सारी रिपोर्टें यहीं रुक जाती हैं:
"यह पार्सर दुर्भावनापूर्ण डेटा स्वीकार करता है।"
यह उपयोगी है, लेकिन यह दिखाने के लिए हमेशा पर्याप्त नहीं है कि बग क्यों मायने रखता है।
इस मामले में, मजबूत रिपोर्ट यह थी:
यह सुरक्षा कहानी को बहुत स्पष्ट बनाता है।
फिक्स न्यूनतम और सही था।
पैच ने वही लापता सुरक्षा नियम जोड़ा जो पहले से remove_sequence() में उपयोग किया जाता था:
घोषित लंबाई उपलब्ध बफर के भीतर फिट होनी चाहिए
वह जांच इन पर लागू की गई:
remove_constructed()remove_implicit()remove_octet_string()एक बार वे सीमा जांच जोड़े जाने के बाद, दुर्भावनापूर्ण/छोटा DER तुरंत इसके साथ अस्वीकार कर दिया गया:
UnexpectedDER: Length longer than the provided buffer
और PoC जो पहले IndexError को ट्रिगर करता था, अब आंतरिक अपवाद पथ तक नहीं पहुंचता था।
यह पार्सिंग के दौरान साफ-साफ विफल हो गया, जो बिल्कुल वही है जो शुरू से होना चाहिए था।
यह उस तरह का फिक्स है जिसे आप एक पार्सर भेद्यता में देखना चाहते हैं:
कोई रीडिज़ाइन नहीं। कोई अस्पष्टता नहीं। बस सही सत्यापन जहां वह गायब था।
मैंने यह सुनिश्चित करने के लिए केंद्रित प्रतिगमन परीक्षण भी जोड़े कि दुर्भावनापूर्ण DER का यह सटीक वर्ग अस्वीकार किया जाता रहे।
नए परीक्षण छोटी-लंबाई अस्वीकृति को कवर करते हैं:
remove_octet_stringremove_constructedremove_implicitयह महत्वपूर्ण था क्योंकि बग एक अजीब रनटाइम पथ के बारे में नहीं था। यह एक सत्यापन नियम के बारे में था जिसे संबंधित DER सहायकों में लगातार धारण करने की आवश्यकता थी।
फिक्स और परीक्षण जोड़े जाने के बाद, पूरा सूट स्थानीय रूप से पास हुआ:
python -m pytest -q
# 2018 passed, 5 skipped
वास्तविक खुलासा कार्य में यह मायने रखता है।
एक फिक्स तब बहुत मजबूत होता है जब वह उन परीक्षणों के साथ आता है जो सीमा को लॉक कर देते हैं।
इस मुद्दे को उचित रूप से मध्यम के रूप में वर्गीकृत किया गया था।
यहां मुख्य प्रभाव उपलब्धता/मजबूती है, गोपनीयता या अखंडता नहीं।
सलाहकार वर्गीकरण था:
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:Lयह समझ में आता है।
दावा यह नहीं है कि दुर्भावनापूर्ण DER हमलावर को कोड निष्पादित करने देता है। दावा यह है कि दुर्भावनापूर्ण DER उस सॉफ्टवेयर में अप्रत्याशित आंतरिक अपवादों को ट्रिगर कर सकता है जो इस लाइब्रेरी का उपयोग करके अविश्वसनीय DER सामग्री को पार्स करता है।
यह एक वास्तविक और बचाव योग्य DoS-शैली पार्सिंग बग है।
यह मुद्दा GitHub Security Advisories के माध्यम से निजी रूप से रिपोर्ट किया गया था।
रिपोर्ट में शामिल था:
IndexError पुनरुत्पादकअनुरक्षक ने मुद्दे को मान्य किया, अनुरोध किया कि फिक्स यूनिट परीक्षणों के साथ लागू हो, और समन्वित फिक्स GHSA अस्थायी निजी फोर्क कार्यप्रवाह के माध्यम से आगे बढ़ा।
CVE हैंडलिंग के दौरान, GitHub ने शुरू में असाइनमेंट से इनकार कर दिया क्योंकि सलाहकार पाठ ऐसा लग रहा था जैसे यह एक से अधिक भेद्यता का वर्णन कर सकता है। स्पष्टीकरण सरल था:
यह एक एकल भेद्यता थी जिसका एक एकल मूल कारण था — अनुचित DER लंबाई सत्यापन — और SigningKey.from_der() IndexError उसी दुर्भावनापूर्ण-इनपुट स्वीकृति का एक डाउनस्ट्रीम परिणाम था, न कि एक अलग स्वतंत्र रूप से सुधार योग्य मुद्दा।
वह स्पष्टीकरण पर्याप्त था, और मुद्दे को सौंपा गया:
CVE-2026-33936
यहाँ सबक "DER मुश्किल है" नहीं है।
हर कोई पहले से जानता है कि DER मुश्किल है।
असली सबक यह है:
दुर्भावनापूर्ण संरचित इनपुट को ठीक उसी बिंदु पर अस्वीकार किया जाना चाहिए जहां पार्सर को पता है कि यह अमान्य है।
यदि आप उस सीमा से चूक जाते हैं, तो बाद का कोड उन धारणाओं पर काम करना शुरू कर देता है जो अब विश्वसनीय नहीं हैं।
इस तरह निम्न-स्तरीय पार्सिंग गलतियाँ सुरक्षा मुद्दे बन जाती हैं।
यह बग राइटअप और ट्राइएज के बारे में कुछ महत्वपूर्ण को भी मजबूत करता है:
"दुर्भावनापूर्ण इनपुट स्वीकार किया गया" कहानी की शुरुआत थी।
"दुर्भावनापूर्ण इनपुट स्वीकार किया गया, फिर कुंजी पार्सिंग के दौरान एक आंतरिक अपवाद पथ में फैल गया" पूरी कहानी थी।
उस अंतर ने मामले को स्पष्ट और सही ढंग से बनाने में मदद की।
यह भेद्यता विदेशी क्रिप्टो के बारे में नहीं थी।
यह एक पार्सर के बारे में था जो दुर्भावनापूर्ण इनपुट पर उससे अधिक समय तक भरोसा करता रहा जितना उसे करना चाहिए था।
एक छोटा DER लंबाई फील्ड सीमा पार कर गया, सत्यापन से बच गया जब इसे अस्वीकार कर दिया जाना चाहिए था, और अंततः कुंजी पार्सिंग में क्रैशी व्यवहार का कारण बना।
यही कारण है कि यह CVE-2026-33936 बन गया।
प्रभावित सहायक पार्सरों में उचित DER लंबाई सीमा जांच लागू करके तय किया गया।
