
0.20.0 से पहले के tough संस्करणों में समस्या (एकाधिक CVE)
मार्च 2025 में, AWS Labs के Tough लाइब्रेरी (TUF – द अपडेट फ्रेमवर्क का Rust क्लाइंट इम्प्लीमेंटेशन) में कई सुरक्षा कमजोरियों का खुलासा हुआ। ये मुद्दे CVE-2025-2885, CVE-2025-2886, CVE-2025-2887 और CVE-2025-2888 के अंतर्गत ट्रैक किए गए हैं, और इन्हें Tough संस्करण 0.20.0 में ठीक किया गया। सुरक्षा इंजीनियर इस दस्तावेज़ का उपयोग प्रत्येक कमजोरी के तकनीकी विवरण, कोडबेस में मूल कारण, और उन्हें हल करने वाले पैच को समझने के लिए कर सकते हैं। Tough < 0.20.0 के सभी उपयोगकर्ताओं को दृढ़ता से सलाह दी जाती है कि वे v0.20.0 या उसके बाद के संस्करण में अपग्रेड करें।
Tough अद्यतन के दौरान Root metadata संस्करण का अनुक्रम में सत्यापन करने में विफल रहा। रिपॉजिटरी को नियंत्रित करने वाला (या man-in-the-middle क्षमता वाला) हमलावर अप्रत्याशित संस्करण संख्या के साथ रूट मेटाडेटा फ़ाइल की आपूर्ति कर सकता था, जिससे क्लाइंट गलत संस्करण को fetch और trust कर लेता। संक्षेप में, Tough ने यह सुनिश्चित नहीं किया कि नए रूट मेटाडेटा का संस्करण पिछले विश्वसनीय संस्करण से ठीक एक अधिक हो, जो TUF के सतत trust श्रृंखला की आवश्यकता का उल्लंघन करता है। इससे रोलबैक या मिक्स-एंड-मैच हमले हो सकते हैं, जहाँ एक पुराने (लेकिन सही ढंग से हस्ताक्षरित) रूट को नवीनतम मानकर स्वीकार कर लिया जाता है, संभावित रूप से सेवानिवृत्त signing कुंजियों या समाप्त हो चुके trust को पुनः लागू करना शामिल है।
tough/src/lib.rs में रूट मेटाडेटा के लिए Tough की अपडेट लॉजिक। कमजोर इम्प्लीमेंटेशन ने केवल यह जाँच की कि नए रूट का संस्करण पुराने से कम नहीं है, बजाय इसके कि यह अगला अनुक्रमिक संस्करण हो। यह चूक TUF स्पेक के नियम का उल्लंघन करती है कि क्लाइंट को मध्यवर्ती रूट संस्करणों को क्रम में डाउनलोड करना चाहिए (कोई संस्करण स्किप नहीं)।कमजोर इम्प्लीमेंटेशन: संस्करण 0.19.x और उससे पहले में, एक नया root.json डाउनलोड करने के बाद, Tough ने हस्ताक्षर सत्यापित किए लेकिन संस्करण की निरंतरता को सख्ती से लागू नहीं किया। इसने नए रूट संस्करण को विश्वसनीय संस्करण के >= किसी भी मान के रूप में अनुमति दी। उदाहरण के लिए, यदि वर्तमान विश्वसनीय रूट संस्करण N था, तो Tough N+2 या उच्चतर संस्करण होने का दावा करने वाले नए रूट को स्वीकार कर लेता (जब तक हस्ताक्षर मान्य थे), N+1 को स्किप करते हुए। नीचे दिया गया कोड स्निपेट फिक्स से पहले की जाँच को दर्शाता है:```rust
// (Prior to fix) Allow new root version to be >= old version – too permissive
ensure!(root.signed.version <= new_root.signed.version, error::OlderMetadataSnafu {
role: RoleType::Root,
current_version: root.signed.version,
new_version: new_root.signed.version
});
एक हमलावर इसका फायदा उठा सकता है <b>एक उच्च-संस्करण root metadata प्रस्तुत करके जो वास्तव में एक पुराना key set है</b>। Tough इसे एक अपडेट समझकर स्वीकार कर लेगा, और [पुरानी कुंजियों से हस्ताक्षरित सामग्री पर भरोसा करेगा](https://github.com/advisories/GHSA-5vmp-m5v2-hx47#:~:text=The%20tough%20client%20will%20trust,with%20a%20previous%20root%20role)।
<b>सुधारा गया कार्यान्वयन:</b> पैच किया गया कोड (Tough 0.20.0 में) स्पष्ट रूप से आवश्यक बनाता है कि नए root का संस्करण पुराने संस्करण से ठीक एक अधिक हो, [commit 0eeb60a](https://github.com/awslabs/tough/commit/0eeb60aefe27f00b65730634b788a1aafb8bf3c6) देखें। यह यह भी सुनिश्चित करता है कि नया संस्करण अधिक है (समानता या कमी को रोकता है) और +1 से बड़ी किसी भी छलांग को रोकता है:```rust
// (Fixed in v0.20.0) Enforce sequential root version update (new_version == old_version + 1)
ensure!(
root.signed.version < new_root.signed.version &&
root.signed.version.get() + 1 == new_root.signed.version.get(),
error::OlderMetadataSnafu {
role: RoleType::Root,
current_version: root.signed.version,
new_version: new_root.signed.version
}
);
यह परिवर्तन सुनिश्चित करता है कि क्लाइंट root मेटाडेटा को क्रम में (N, N+1, N+2, ...) डाउनलोड और लागू करता है, बिना किसी को छोड़े। यदि कोई root मेटाडेटा फ़ाइल ऐसे संस्करण के साथ मिलती है जो ठीक old_version+1 नहीं है, तो Tough अब इसे संभावित हमले के रूप में मानता है और अपडेट को रोक देता है।
Tough ने TUF द्वारा परिभाषित “terminating” delegated targets roles को गलत तरीके से संभाला। एक TUF रिपॉजिटरी में, किसी delegation को terminating चिह्नित किया जा सकता है, जिसका अर्थ है कि यदि target lookup उस delegation तक पहुँचता है और target वहाँ नहीं मिलता है, तो खोज रुक जानी चाहिए (और अन्य निचली-प्राथमिकता वाली delegations पर जारी नहीं रहनी चाहिए)। (देखें यहाँ) एक तर्क त्रुटि के कारण, Tough इस मामले में खोज को समाप्त करने में विफल रहा – यह बाद की delegations की खोज जारी रखता था, भले ही उसे रुक जाना चाहिए था। इससे कोई हमलावर निचली-प्राथमिकता वाली delegation को नियंत्रित करके उन targets के लिए सामग्री परोस सकता था जिन्हें उन्हें नियंत्रित नहीं करना चाहिए, इच्छित trust boundaries को दरकिनार करते हुए।
tough/src/editor/targets.rs में target lookup एल्गोरिथ्म (और संबंधित delegation resolution कोड)। कमजोर कोड delegations पर terminating फ्लैग को सही ढंग से संभाल नहीं पाता था। किसी target की खोज में delegations के माध्यम से iteration करते समय, Tough अगली delegation पर आगे बढ़ता था, भले ही वर्तमान delegation terminating चिह्नित हो और उसमें कोई match न हो, जो TUF spec के विपरीत है।कमजोर कार्यान्वयन: Tough <0.20.0 में, find_target() तर्क केवल सभी संभावित delegated roles के माध्यम से recurse या loop होता था, जब तक कि कोई target नहीं मिल जाता या सभी समाप्त नहीं हो जाते। इसमें किसी terminating role का सामना करने पर कोई फ्लैग सेट या break नहीं किया जाता था। पुराने व्यवहार का स्यूडोकोड:```rust
for role in delegation_chain {
if role.has_target(target) {
return target_metadata;
}
// Missing: if role is terminating and target not found, should break.
// Tough erroneously continues to next delegation.
}
इसका मतलब है कि एक निम्न-प्राथमिकता वाला प्रतिनिधि (जिसे उसके ऊपर किसी समाप्ति प्रतिनिधिमंडल के बाद अनदेखा किया जाना चाहिए) फिर भी परामर्श में लिया जा सकता है और एक दुर्भावनापूर्ण लक्ष्य फ़ाइल प्रदान कर सकता है।