
प्लेन का V2 एसेट सबसिस्टम उपयुक्त सदस्यता जांच लागू किए बिना workspace slugs और asset UUIDs पर भरोसा करता था, जिससे एक प्रमाणित उपयोगकर्ता अन्य workspaces में एसेट्स को पढ़, कॉपी, हटा और ओवरराइट कर सकता था।
प्लेन के V2 एसेट सबसिस्टम ने सही सदस्यता जाँच लागू किए बिना विश्वसनीय वर्कस्पेस स्लग और एसेट UUID पर भरोसा किया, जिससे एक प्रमाणित उपयोगकर्ता दूसरे वर्कस्पेस में एसेट्स को पढ़, कॉपी, हटा और अधिलेखित कर सकता था।
मुझे यह समस्या प्लेन, ओपन-सोर्स प्रोजेक्ट मैनेजमेंट प्लेटफ़ॉर्म, की समीक्षा करते समय मिली, जिसमें एक बहुत ही विशिष्ट प्रश्न था:
क्या V2 एसेट एंडपॉइंट वास्तव में वर्कस्पेस सीमाएँ लागू करते हैं, या वे हमलावर द्वारा प्रदान किए गए वर्कस्पेस स्लग और एसेट आईडी पर बहुत अधिक भरोसा करते हैं?
इस मामले में, उत्तर नहीं था।
प्लेन के V2 एसेट सबसिस्टम ने दो संबंधित प्राधिकरण दोष उजागर किए जिन्होंने किसी भी प्रमाणित उपयोगकर्ता के लिए वर्कस्पेस अलगाव को तोड़ दिया:
इसने क्रॉस-वर्कस्पेस एसेट दुरुपयोग संभव बना दिया।
मेरे मान्य किए गए PoC में, वर्कस्पेस ब्रावो में एक सामान्य उपयोगकर्ता सक्षम था:
उस समस्या को बाद में CVE-2026-46558 निर्दिष्ट किया गया।
प्लेन: GitHub पर प्लेन
CVE: CVE-2026-46558
इसने प्लेन को प्रभावित किया, जो अपनी आधिकारिक साइट पर दुनिया भर में 50,000+ टीमों द्वारा उपयोग किए जाने के रूप में प्रस्तुत किया जाता है। प्लेन मजबूत ओपन-सोर्स अपनाने पर भी प्रकाश डालता है, जिसमें 46,000+ GitHub स्टार और 1,000,000+ Docker पुल शामिल हैं, और Tencent, Accenture, Microsoft, और Amazon जैसे संगठनों को प्रदर्शित करता है।
वर्कस्पेस B में प्रमाणित हमलावर → वर्कस्पेस-स्तरीय V2 एसेट रूट उचित सदस्यता जाँच के बिना लक्ष्य वर्कस्पेस स्लग और एसेट UUID पर भरोसा करता है → वर्कस्पेस A एसेट्स के विरुद्ध प्रिसाइन्ड रीड/पैच/डिलीट + डुप्लिकेट-एसेट्स स्रोत लुकअप अपलोड किए गए स्रोत UUID पर भरोसा करता है → क्रॉस-वर्कस्पेस प्रकटीकरण, प्रतिलिपि, विलोपन, और ब्रांडिंग अधिलेखन
प्लेन एक ओपन-सोर्स प्रोजेक्ट मैनेजमेंट प्लेटफ़ॉर्म है जिसका उपयोग प्रबंधन के लिए किया जाता है:
इसका मतलब है कि इसका एसेट सबसिस्टम एक वास्तविक विश्वास सीमा पर बैठता है।
यहाँ महत्वपूर्ण प्रश्न यह नहीं था कि क्या प्लेन अपलोड का समर्थन करता है।
असली प्रश्न था:
क्या प्लेन वर्कस्पेस अलगाव लागू करता है जब एक प्रमाणित उपयोगकर्ता दूसरे वर्कस्पेस के स्वामित्व वाले एसेट्स को संदर्भित करता है?
इस मामले में, ऐसा नहीं हुआ।
बहु-किरायेदार अनुप्रयोग समीक्षाएँ अक्सर पहले स्पष्ट व्यवस्थापक एंडपॉइंट या प्रत्यक्ष सेटिंग्स अपडेट पर ध्यान केंद्रित करती हैं।
यह एक बहुत ही सामान्य और वास्तविक बग वर्ग को अनदेखा करता है:
साझा फ़ाइल या एसेट सबसिस्टम के माध्यम से द्वितीयक वस्तु पहुँच
एसेट सिस्टम गलत होना आसान है क्योंकि वे अक्सर संयोजित करते हैं:
यह ठीक वही जगह है जहाँ किरायेदार सीमाएँ चुपचाप कमजोर हो जाती हैं।
यह समस्या भंडारण भ्रष्टाचार के बारे में नहीं थी। यह S3 के बारे में ही नहीं थी। यह अपलोड MIME हैंडलिंग के बारे में नहीं थी।
यह एक प्राधिकरण सीमा विफलता थी:
यह एक वास्तविक कमजोरी पैदा करने के लिए पर्याप्त है।
मैंने प्लेन में बेतरतीब ढंग से यादृच्छिक एंडपॉइंट फ़ज़ करके या बिना किसी मॉडल के UUID का अनुमान लगाकर संपर्क नहीं किया।
सबसे मजबूत दृष्टिकोण पहले सबसे आशाजनक अलगाव सीमा की पहचान करना था।
प्लेन के लिए, वह था V2 एसेट सबसिस्टम।
क्यों?
क्योंकि एक साझा एसेट सिस्टम तब खतरनाक हो जाता है जब:
यह जाँच करने के लिए सही सीमा थी।
और यह ठीक वही जगह थी जहाँ बग रहता था।
यह वास्तव में एक ही सबसिस्टम में दो संबंधित प्राधिकरण विफलताएँ थीं।
वर्कस्पेस-स्तरीय एसेट रूट इसके माध्यम से उजागर हुए:
apps/api/plane/app/urls/asset.py:50-56कमजोर हैंडलर इसमें थे:
apps/api/plane/app/views/asset/v2.py:314apps/api/plane/app/views/asset/v2.py:379apps/api/plane/app/views/asset/v2.py:400apps/api/plane/app/views/asset/v2.py:409समस्या सरल थी।
WorkspaceFileAssetEndpoint ने एक वर्कस्पेस स्लग और एसेट UUID स्वीकार किया, फिर सीधे वस्तुओं को हल किया जैसे:
workspace = Workspace.objects.get(slug=slug)
और:
asset = FileAsset.objects.get(id=asset_id, workspace__slug=slug)
बिना पहले यह लागू किए कि कॉल करने वाला वास्तव में उस लक्ष्य वर्कस्पेस का एक अधिकृत सदस्य था।
इसका मतलब था कि एंडपॉइंट अभी भी कर सकता था:
दूसरे वर्कस्पेस की वस्तुओं के लिए।
डुप्लिकेट-एसेट्स रूट इसके माध्यम से मैप किया गया:
apps/api/plane/app/urls/asset.py:100-101कमजोर तर्क इसमें था:
apps/api/plane/app/views/asset/v2.py:736-780गंतव्य वर्कस्पेस में एक प्राधिकरण डेकोरेटर था। लेकिन स्रोत एसेट लुकअप में नहीं था।
स्रोत वस्तु को इसके साथ लोड किया गया:
original_asset = FileAsset.objects.filter(id=asset_id, is_uploaded=True).first()
इसका मतलब था कि कॉल करने वाले को केवल चाहिए था:
कोई जाँच नहीं थी कि कॉल करने वाला उस स्रोत वर्कस्पेस से संबंधित है जो वास्तव में उस एसेट का मालिक था।
यह पूरा दूसरा बग है।
महत्वपूर्ण अंतर क्रॉस-वर्कस्पेस प्रभाव है।
बहुत सारे प्राधिकरण बग को कम करके आंका जाता है:
"इसके लिए अभी भी लॉगिन आवश्यक है"
यह बिंदु से चूक जाता है।
असली सवाल यह नहीं है:
"क्या कॉल करने वाला प्रमाणित है?"
असली सवाल है:
"क्या कॉल करने वाला उस विशिष्ट वर्कस्पेस और विशिष्ट एसेट के लिए अधिकृत है जिस पर कार्रवाई की जा रही है?"
प्लेन में, वह उत्तर नहीं था।
यह वही है जो सामान्य वस्तु हैंडलिंग जैसा दिख सकता है, उसे एक वास्तविक बहु-किरायेदार सुरक्षा मुद्दे में बदल देता है।
इसके बीच एक स्पष्ट अंतर है:
यह मुद्दा दूसरे मामले में दृढ़ता से था।
मैंने स्थानीय रूप से प्लेन कम्युनिटी एडिशन 1.2.3 के विरुद्ध दो असंबंधित वर्कस्पेस में दो सामान्य उपयोगकर्ताओं का उपयोग करके समस्या को मान्य किया:
alpha-20260323072017 में Alphabravo-20260323072017 में Bravoमैंने Alpha का उपयोग एक प्रोजेक्ट इश्यू में एक वैध निजी अपलोड किया गया एसेट बनाने के लिए किया।
मेरे रन में मान्य निजी एसेट ID थी:
6ed6ed62-d1b2-4399-8220-336c01b7d72c
Bravo के रूप में, मैंने अनुरोध किया:
GET /api/assets/v2/workspaces/alpha-20260323072017/6ed6ed62-d1b2-4399-8220-336c01b7d72c/
प्लेन ने लौटाया:
HTTP/1.1 302 Found
Alpha के एसेट के लिए एक प्रिसाइन्ड डाउनलोड URL के साथ।
डाउनलोड की गई फ़ाइल हैश Alpha के मूल निजी एसेट से बिल्कुल मेल खाती है:
original: 0d4d070f550ba59ba6b30bee62343cf68ea221af7034f131f72f6409cf5a598e
unauthorized read: 0d4d070f550ba59ba6b30bee62343cf68ea221af7034f131f72f6409cf5a598e
इसने साबित किया कि रीड पथ वर्कस्पेस सीमाओं को सफलतापूर्वक पार कर गया।