समस्या और लागू होने वाला परिदृश्य
एक B2B डॉक्यूमेंट सर्विस एक शेयर्ड डेटाबेस का उपयोग करती है। एक यूज़र कई टेनेंट्स से संबंधित हो सकता है और प्रत्येक में उसकी भूमिका viewer, editor, या admin हो सकती है। एक डॉक्यूमेंट को सीधे उसी टेनेंट के किसी सदस्य के साथ भी शेयर किया जा सकता है। यह सर्विस सिंगल-डॉक्यूमेंट रीड, अपडेट और डिलीट APIs, बल्क एक्सपोर्ट और एसिंक्रोनस आर्काइव जनरेशन प्रदान करती है। JWT सिग्नेचर, एक्सपायरी और ऑडियंस वैलिडेशन पहले से काम कर रहे हैं, लेकिन लेगेसी कोड क्लाइंट द्वारा दिए गए document_id के ज़रिए ग्लोबली डॉक्यूमेंट लोड करता है और फिर केवल यह चेक करता है कि रिक्वेस्ट ऑथेंटिकेटेड है या नहीं।
एक अटैकर ऑडिट एंट्री, शेयर लिंक या किसी अन्य API से एक वैलिड UUID प्राप्त करता है और अपने डॉक्यूमेंट ID को इससे बदल देता है। UUID का अनुमान लगाना (enumerate करना) कठिन है, लेकिन सर्वर तब भी डॉक्यूमेंट को डिस्क्लोज़ या मॉडिफाई कर देगा जब तक कि वह यह चेक न करे कि वर्तमान सब्जेक्ट एक्टिव टेनेंट में इस रिसोर्स पर यह एक्शन कर सकता है या नहीं। OWASP इसे Broken Object Level Authorization (BOLA) कहता है; सामान्य वेब-सिक्योरिटी सामग्री में Insecure Direct Object Reference (IDOR) का भी उपयोग किया जाता है। कोई ऑब्जेक्ट आइडेंटिफायर किसी पाथ, क्वेरी पैरामीटर, हेडर, JSON बॉडी, GraphQL वेरिएबल, फ़ाइलनेम या बल्क लिस्ट में दिखाई दे सकता है।
दो सार्वजनिक API इंटरव्यू-तैयारी पेज स्पष्ट रूप से उम्मीदवारों से IDOR को समझाने या टेस्ट करने के लिए कहते हैं। जनवरी 2026 की एक सार्वजनिक चर्चा में पूछा गया है कि क्या ऑब्जेक्ट IDs को एन्क्रिप्ट करने से IDOR ठीक हो जाता है, जिससे पता चलता है कि "ID छिपाना" एक व्यावहारिक गलतफहमी बनी हुई है जिसका उम्मीदवारों को विश्लेषण करने की आवश्यकता है। OWASP API Security Top 10 API1:2023 और 2026 का एक सार्वजनिक अनुभवजन्य अध्ययन अतिरिक्त जोखिम और तकनीकी संदर्भ प्रदान करते हैं। यह साक्ष्य इसके प्रतिनिधि होने का समर्थन करता है; यह किसी विशेष कंपनी के प्रश्न या इंटरव्यू आवृत्ति को स्थापित नहीं करता है।
यह एक बैकएंड प्रश्न है क्योंकि इसका मुख्य कार्य ऑथेंटिकेटेड पहचान, टेनेंट संबंधों, रिसोर्स विशेषताओं और एक्शन्स को APIs, डेटा एक्सेस, ट्रांज़ैक्शन्स, कैशे और वर्कर्स के पार एक ऑथराइजेशन बाउंड्री में ले जाना है। मौजूदा OAuth लेख पहचान और ऑथराइजेशन-कोड फ़्लो को कवर करता है, SQL इंजेक्शन क्वेरी संरचना को कवर करता है, और SSRF आउटबाउंड डेस्टिनेशन ऑथराइजेशन को कवर करता है। इनमें से कोई भी ऑब्जेक्ट-लेवल एक्सेस का उत्तर नहीं देता है।
इंटरव्यूअर क्या मूल्यांकन कर रहा है
पहला संकेत सटीक शब्दावली है। ऑथेंटिकेशन उत्तर देता है "कॉल कौन कर रहा है?" ऑब्जेक्ट-लेवल ऑथराइजेशन उत्तर देता है "क्या यह सब्जेक्ट अभी इस ऑब्जेक्ट पर यह एक्शन कर सकता है?" एक यूज़र जो PATCH /documents/{id} को कॉल कर सकता है लेकिन किसी अन्य टेनेंट के डॉक्यूमेंट को मॉडिफाई नहीं कर सकता, BOLA को उजागर करता है। एक सामान्य सदस्य का केवल-एडमिन वाले बल्क-डिलीट फ़ंक्शन तक पहुँचना Broken Function Level Authorization के करीब है। किसी यूज़र को अपने स्वयं के डॉक्यूमेंट पर संरक्षित owner_id प्रॉपर्टी को अपडेट करने की अनुमति देना एक ऑब्जेक्ट-प्रॉपर्टी ऑथराइजेशन समस्या है।
दूसरा संकेत एक संपूर्ण ऑथराइजेशन मॉडल है। केवल document.owner_id == user.id की तुलना करना टेनेंट रोल्स, टीम शेयरिंग, रीड-ओनली राइट्स, रिवोकेशन और टेम्पररी सपोर्ट एक्सेस को छोड़ देता है। एक ठोस उत्तर एक निर्णय को स्पष्ट बनाता है:
allow(subject, tenant, action, resource, context) -> decision + reasonटेनेंट एक वेरिफाइड मेंबरशिप से आता है। एक्शन्स read, update, delete, share, और export में अंतर करते हैं। रिसोर्स विशेषताओं में टेनेंट, स्टेट, ओनर और शेयरिंग संबंध शामिल हैं। कॉन्टेक्स्ट में एक टेम्पररी सपोर्ट ग्रांट और पॉलिसी वर्ज़न शामिल हो सकता है। यदि कोई अलाउ नियम मैच नहीं करता है, तो निर्णय डिनाई होता है।
तीसरा संकेत उस बाउंड्री को लागू करना है जहाँ डेटा सेलेक्ट और चेंज किया जाता है। findById(id) के साथ ग्लोबली लोड करना और चेक जोड़ने के लिए एक कंट्रोलर पर निर्भर रहना बल्क एंडपॉइंट्स, वर्कर्स, कैशे और नए रूट्स के माध्यम से बाईपास बनाता है। अनुशंसित पाथ एक ऑथराइज्ड डेटा सेट से क्वेरी करता है। एक म्यूटेशन स्कोप और वर्ज़न की शर्तों को उसी स्टेटमेंट या ट्रांज़ैक्शन में ले जाता है और प्रभावित-पंक्तियों की संख्या (affected-row count) को सत्यापित करता है।
चौथा संकेत डिफेंस-इन-डेप्थ की सीमाओं को समझना है। रैंडम UUIDs, 404 रिस्पॉन्स, रेट लिमिट्स और PostgreSQL Row-Level Security (RLS) सभी मदद करते हैं, लेकिन इनमें से कोई भी संपूर्ण बिज़नेस ऑथराइजेशन की जगह नहीं लेता है। PostgreSQL 18 डॉक्यूमेंटेशन में यह भी कहा गया है कि सुपरयूज़र्स, BYPASSRLS रोल्स और सामान्यतः टेबल ओनर्स RLS को बाईपास करते हैं। पॉलिसी इनेबलमेंट, कनेक्शन रोल्स और प्रति-रिक्वेस्ट टेनेंट कॉन्टेक्स्ट को सत्यापित किया जाना चाहिए।
अंतिम संकेत यह साबित करना है कि हर पाथ क्रॉस-ऑब्जेक्ट एक्सेस को डिनाई करता है। अपने स्वयं के डॉक्यूमेंट के लिए एक सफल GET एक फंक्शनल टेस्ट है। सिक्योरिटी टेस्ट्स कई अकाउंट्स, टेनेंट्स, रोल्स और ज्ञात वैलिड विदेशी ऑब्जेक्ट IDs का उपयोग करते हैं। वे रीड्स, राइट्स, डिलीट्स, बल्क ऑपरेशन्स, एक्सपोर्ट्स, डाउनलोड्स, GraphQL, कैशे हिट्स और वर्कर एक्ज़ीक्यूशन को कवर करते हैं, और यह सुनिश्चित करते हैं कि कोई डेटाबेस, ऑब्जेक्ट-स्टोरेज या मैसेजिंग साइड इफेक्ट नहीं हुआ।
उत्तर देने से पहले स्पष्ट करने योग्य प्रश्न
- टेनेंट का चयन कैसे किया जाता है? एक यूज़र एक्टिव टेनेंट्स बदल सकता है, लेकिन एक क्लाइंट
X-Tenant-IDकेवल एक
पसंद व्यक्त करता है। सर्वर को हेडर पर भरोसा करने के बजाय ऑथेंटिकेटेड पहचान के लिए मेंबरशिप को फिर से वैलिडेट करना चाहिए।
- अनुमति क्या निर्धारित करती है? क्या यह केवल एक टेनेंट रोल है, या ओनरशिप, टीम मेंबरशिप, डायरेक्ट शेयरिंग,
डॉक्यूमेंट स्टेट और टेम्पररी सपोर्ट ग्रांट्स भी हैं? अधिक डाइनैमिक नियमों के लिए एक केंद्रीय पॉलिसी और स्थिर ऑडिट कारणों की आवश्यकता होती है।
- किन एक्शन्स के लिए अलग अनुमति की आवश्यकता होती है? रीड में डाउनलोड, एक्सपोर्ट, शेयर
या डिलीट स्वचालित रूप से शामिल नहीं होता है। एक बल्क ऑपरेशन प्रत्येक ऑब्जेक्ट पर समान एक्शन-लेवल निर्णय लागू करता है।
- क्या डिनायल पर 403 या 404 रिटर्न होना चाहिए? यदि किसी बाहरी ऑब्जेक्ट ID को अस्तित्व प्रकट नहीं करना चाहिए, तो मिसिंग और इनविज़िबल
एक समान 404 कॉन्ट्रैक्ट साझा कर सकते हैं। अपर्याप्त एक्शन अनुमति वाला एक विज़िबल सेम-टेनेंट ऑब्जेक्ट प्रोडक्ट कॉन्ट्रैक्ट के तहत 403 लौटा सकता है। कोई भी रिस्पॉन्स संवेदनशील अंतर को उजागर नहीं करना चाहिए।
- क्या जॉब्स वर्तमान अनुमति का उपयोग करती हैं या सबमिशन-टाइम स्नैपशॉट का? यह डिज़ाइन एनक्यू (enqueue) के समय और फिर
एक्ज़ीक्यूशन के समय चेक करता है, ताकि रिवोकेशन के बाद कतारबद्ध एक्सपोर्ट रुक जाए। यदि इम्यूटेबल स्नैपशॉट अधिकारों की आवश्यकता है, तो एक स्पष्ट, स्कोप्ड, एक्सपायरिंग ग्रांट को मॉडल करें।
- क्या सपोर्ट स्टाफ टेनेंट्स तक पहुँच सकता है? यदि हाँ, तो एक अलग जस्ट-इन-टाइम पाथ का उपयोग करें जिसके लिए टिकट, कारण,
मंजूरी, एक्सपायरी और पूर्ण ऑडिट की आवश्यकता हो। सामान्य एप्लिकेशन कनेक्शन को स्थायी ग्लोबल-एडमिन स्विच न दें।
- क्या PostgreSQL RLS का उपयोग किया जाएगा? यह उत्तर प्राइमरी कंट्रोल के रूप में एप्लिकेशन टेनेंट स्कोपिंग का उपयोग करता है और चूक से बचने के लिए
RLS का। अन्य संयोजन मान्य हैं यदि डेटाबेस रोल्स, पूल कॉन्टेक्स्ट, माइग्रेशन्स और वर्कर्स अपनी गारंटियों को बनाए रखते हैं।
30-सेकंड उत्तर का ढाँचा
"मैं ऑथराइजेशन को subject + tenant + action + resource + context के रूप में व्यक्त करूँगा और डिफ़ॉल्ट रूप से डिनाई करूँगा। ऑथेंटिकेशन मिडलवेयर केवल सब्जेक्ट स्थापित करता है। एक्टिव टेनेंट एक वेरिफाइड मेंबरशिप से आना चाहिए। डेटा लेयर अनस्कोप्ड डॉक्यूमेंट लुकअप को एक्सपोज़ नहीं करती है: रीड्स tenant_id + document_id का उपयोग करते हैं, जिसके बाद रोल, ओनर और शेयरिंग पर एक्शन पॉलिसी लागू होती है। अपडेट्स और डिलीट्स उन शर्तों को उसी स्टेटमेंट या ट्रांज़ैक्शन में ले जाते हैं; शून्य प्रभावित पंक्तियों को इनविज़िबल के रूप में हैंडल किया जाता है। एक UUID इन्यूमरेशन को कम करता है लेकिन कभी भी एक्सेस कंट्रोल की जगह नहीं लेता है।
बल्क, कैशे, डाउनलोड और एक्सपोर्ट पाथ्स समान नियमों का उपयोग करते हैं। कैशे कीज़ में टेनेंट शामिल होता है; कैपेबिलिटी लिंक्स रिसोर्स, एक्शन और एक्सपायरी को बाइंड करते हैं; और एक जॉब एनक्यू और एक्ज़ीक्यूशन के समय चेक करती है। PostgreSQL RLS गलतियों से बचाव कर सकता है, बशर्ते एप्लिकेशन रोल इसे बाईपास न कर सके और पूल टेनेंट स्विचिंग का परीक्षण किया गया हो। अंत में, मैं एक टू-टेनेंट, मल्टी-रोल मैट्रिक्स में पाथ्स, बॉडीज़ और बल्क लिस्ट्स में IDs को सब्स्टिट्यूट करूँगा और पुष्टि करूँगा कि कोई भी रिस्पॉन्स, डेटा, फ़ाइल या मैसेज टेनेंट बाउंड्री को पार न करे।"
चरण-दर-चरण विस्तृत विवरण
चरण 1: ऑथराइजेशन टुपल्स और ऑब्जेक्ट-एंट्री पॉइंट्स की सूची बनाएँ
कंट्रोलर्स में रोल के नामों को बिखेरने से पहले बिज़नेस रूल्स को एक मैट्रिक्स के रूप में लिखें:
| सब्जेक्ट संबंध | read | update | delete | share | export |
|---|---|---|---|---|---|
टेनेंट viewer, शेयर्ड नहीं | Deny | Deny | Deny | Deny | Deny |
टेनेंट viewer, सीधे शेयर्ड | Allow | Deny | Deny | Deny | Allow या प्रोडक्ट-विशिष्ट |
टेनेंट editor | Allow | Allow | Deny | पॉलिसी-विशिष्ट | Allow |
| डॉक्यूमेंट ओनर | Allow | Allow | पॉलिसी-विशिष्ट | Allow | Allow |
टेनेंट admin | Allow | Allow | Allow | Allow | Allow |
यह तालिका एक परिदृश्य धारणा है। प्रोडक्ट और सिक्योरिटी ओनर्स को वास्तविक मैट्रिक्स को मंजूरी देनी चाहिए और प्रत्येक अलाउ नियम को उचित ठहराना चाहिए। डिफ़ॉल्ट डिनाई का अर्थ है कि एक नया एक्शन, अज्ञात रोल, गायब टेनेंट कॉन्टेक्स्ट, या पॉलिसी एरर क्लोज़्ड फ़ेल (fail closed) होता है।
फिर ऑब्जेक्ट-एंट्री पॉइंट्स की सूची बनाएँ: पाथ पैरामीटर्स, क्वेरी फ़िल्टर्स, बॉडीज़, बल्क एरेज़, GraphQL नोड्स, शेयर टोकन्स, ऑब्जेक्ट-स्टोर कीज़, कैशे कीज़, मैसेजेस और जॉब्स। OWASP की परिभाषा में क्रमिक (sequential) ID की आवश्यकता नहीं है। UUIDs, फ़ाइलनेम और जेनेरिक स्ट्रिंग्स भी रेफरेंस हैं। प्रत्येक एंट्री के लिए, सब्जेक्ट सोर्स, टेनेंट सोर्स, एक्शन, लुकअप मेथड और अंतिम साइड इफेक्ट को रिकॉर्ड करें। वह प्रक्रिया बाईपास को उजागर करती है।
चरण 2: ऑथेंटिकेटेड पहचान से एक विश्वसनीय टेनेंट प्राप्त करें
एक वेरिफाइड JWT एक स्थिर user_id प्रदान करता है; यह हर लंबे समय तक चलने वाले रोल क्लेम को वर्तमान नहीं बनाता है या अलग से दिए गए टेनेंट ID को विश्वसनीय नहीं बनाता है। जब कोई यूज़र tenant_b चुनता है, तो सर्वर वर्तमान मेंबरशिप को हल करता है और एक रिक्वेस्ट-स्कोप्ड AuthContext बनाता है:
AuthContext {
user_id,
tenant_id,
membership_id,
roles,
policy_version,
support_grant_id?
}मिडलवेयर सुनिश्चित करता है कि कॉन्टेक्स्ट मौजूद है; डोमेन पॉलिसी अभी भी रिसोर्स एक्शन्स तय करती है। कनेक्शन पूल्स, कंज्यूमर्स और समवर्ती रिक्वेस्ट्स को एक म्यूटेबल ग्लोबल टेनेंट साझा नहीं करना चाहिए। प्रत्येक ट्रांज़ैक्शन के अंदर डेटाबेस कॉन्टेक्स्ट सेट करें और कनेक्शन वापस करने से पहले इसे साफ़ करें ताकि एक रिक्वेस्ट पिछले टेनेंट को इनहेरिट न कर सके।
चरण 3: टेनेंट स्कोप को क्वेरीज़ और डेटा बाधाओं (constraints) में डालें
असुरक्षित क्वेरी ग्लोबली लोड करती है:
SELECT * FROM documents WHERE id = :document_id;बेसिक बाउंड्री में विश्वसनीय टेनेंट शामिल होता है:
SELECT *
FROM documents
WHERE tenant_id = :auth_tenant_id
AND id = :document_id;यदि डायरेक्ट शेयरिंग विजिबिलिटी निर्धारित करती है, तो स्कोप्ड क्वेरी के अंदर शेयर संबंध को जॉइन करें या केवल सेम-टेनेंट रिसोर्स लोड करें और इसे एक सेंट्रल पॉलिसी इंजन को पास करें। बॉडी से tenant_id को इस प्रेडिकेट में कभी कॉपी न करें। बाहरी रूप से, शून्य पंक्तियाँ लगातार 404 उत्पन्न कर सकती हैं ताकि "दूसरे टेनेंट में मौजूद है" और "मौजूद नहीं है" में अंतर न किया जा सके।
स्कीमा डिज़ाइन गलतियों को कठिन बनाता है। शेयर, वर्ज़न, अटैचमेंट और एक्सपोर्ट-आइटम टेबल्स सभी में tenant_id होता है। जहाँ उपयुक्त हो, यूनिक और फॉरेन कीज़ (tenant_id, resource_id) का उपयोग करती हैं ताकि एक टेनेंट का चाइल्ड दूसरे टेनेंट के पेरेंट को पॉइंट न कर सके। एप्लिकेशन ऑथराइजेशन आवश्यक बना रहता है; बाधाएं राइट टाइम पर आकस्मिक क्रॉस-टेनेंट संबंधों को अस्वीकार करती हैं।
चरण 4: ऑथराइजेशन और म्यूटेशन को एक शुद्धता सीमा (correctness boundary) में रखें
"लोड करें, एप्लिकेशन कोड में ऑथराइज करें, बाद में अपडेट करें" में टाइम-ऑफ़-चेक/टाइम-ऑफ़-यूज़ रेस होती है। चरणों के बीच अनुमति या डॉक्यूमेंट की स्थिति बदल सकती है। एक साधारण पॉलिसी एक सशर्त अपडेट (conditional update) का उपयोग कर सकती है:
UPDATE documents
SET title = :title, version = version + 1
WHERE tenant_id = :auth_tenant_id
AND id = :document_id
AND version = :expected_version
AND (
owner_id = :user_id
OR :can_edit_tenant_documents
);जब शून्य पंक्तियाँ प्रभावित हों, तो कोई मैसेज पब्लिश न करें, सफलता ऑडिट एंट्री न लिखें, या कैशे अपडेट न करें। जटिल शेयरिंग एक ट्रांज़ैक्शन में प्रासंगिक मेंबरशिप और रिसोर्स वर्ज़न्स को लॉक कर सकती है, या पॉलिसी को डेटाबेस प्रेडिकेट में संकलित कर सकती है। ऑथराइजेशन साक्ष्य और साइड इफेक्ट्स को एक स्पष्ट ट्रांज़ैक्शन/वर्ज़न बाउंड्री साझा करनी चाहिए; एक पुराना स्नैपशॉट बिना शर्त बाद के राइट को ऑथराइज नहीं कर सकता।
बल्क ऑपरेशन्स को एक एटॉमिजिटी कॉन्ट्रैक्ट की आवश्यकता होती है। यह परिदृश्य ऑल-ऑर-नथिंग का उपयोग करता है: सभी IDs को नॉर्मलाइज़ और डिडुप्लिकेट करें, एक विश्वसनीय टेनेंट और एक्शन के तहत ऑथराइज्ड सेट को क्वेरी करें, और यदि काउंट्स भिन्न हैं तो बैच को अस्वीकार कर दें। विज़िबल सबसेट को चुपचाप एक्सपोर्ट करना अस्तित्व का ओरैcle (existence oracle) बन सकता है। एक प्रति-आइटम प्रोडक्ट कॉन्ट्रैक्ट भी संभव है, लेकिन इसे प्रत्येक ऑब्जेक्ट को ऑथराइज करना होगा और अस्वीकार किए गए आइटम्स के लिए एक गैर-प्रकटीकरण (non-disclosing) परिणाम का उपयोग करना होगा।
चरण 5: कैशे, डाउनलोड्स और एसिंक्रोनस जॉब्स को कवर करें
कैशे की में कम से कम टेनेंट और रिसोर्स वर्ज़न शामिल होता है, जैसे कि document:{tenant_id}:{document_id}:{version}। एक हिट डेटा पुनर्प्राप्त करता है; यह वर्तमान एक्शन ऑथराइजेशन को छोड़ता नहीं है। यदि निर्णयों को कैश किया जाता है, तो की में सब्जेक्ट, टेनेंट, एक्शन, रिसोर्स, रिलेशनशिप या पॉलिसी वर्ज़न और रिवोकेशन शामिल होना चाहिए। जटिल सिस्टम अक्सर रिलेशनशिप डेटा को कैश करने और एक छोटे निर्णय की पुनर्गणना करने के लिए अधिक सुरक्षित होते हैं।
एक प्रीसाइन्ड डाउनलोड URL एक अल्पकालिक क्षमता (capability) है। एक बार जारी होने के बाद, एक धारक अपने जीवनकाल के दौरान स्टोरेज तक पहुँच सकता है। इसे जारी करने से पहले download की जाँच करें और रिसोर्स, एक्शन, एक्सपायरी और कंटेंट डिस्पोज़िशन को बाइंड करें। संवेदनशील डॉक्यूमेंट्स छोटे जीवनकाल, वन-टाइम या प्रॉक्सीड डाउनलोड्स और जहाँ आवश्यक हो रिवोकेशन का उपयोग करते हैं। एक सिग्नेचर यह साबित करता है कि सर्वर ने URL जारी किया है; यह किसी अनधिकृत कॉलर को इसे प्राप्त करने की अनुमति नहीं देता है।
एक एक्सपोर्ट दो क्षणों में जाँच करता है। API एनक्यू करने से पहले प्रत्येक डॉक्यूमेंट पर export को सत्यापित करता है। निष्पादन के समय, वर्कर वर्तमान मेंबरशिप और रिसोर्स अनुमति को फिर से लोड करने के लिए जॉब में सब्जेक्ट और टेनेंट संदर्भों का उपयोग करता है। रिवोक की गई मेंबरशिप, टेनेंट परिवर्तन, या एक्सपायर हो चुका सपोर्ट ग्रांट डाउनलोड करने योग्य आर्टिफैक्ट मौजूद होने से पहले जॉब को रोक देता है। जॉब पेलोड कॉलर द्वारा दिए गए एडमिन फ़्लैग को स्वीकार नहीं कर सकता है या रोल ऐरे को हमेशा के लिए सुरक्षित नहीं रख सकता है।
चरण 6: PostgreSQL RLS को टेस्ट करने योग्य डिफेंस-इन-डेप्थ के रूप में मानें
शेयर्ड टेबल्स RLS को सक्षम कर सकती हैं ताकि एक पॉलिसी विश्वसनीय ट्रांज़ैक्शन टेनेंट द्वारा मौजूदा पंक्तियों को फ़िल्टर करे और WITH CHECK इन्सर्ट या अपडेट की गई पंक्तियों को बाधित करे। जब कोई पॉलिसी लागू न हो तो डिफ़ॉल्ट डिनाई एक वांछनीय विफलता मोड (failure mode) है। रिलीज़ से पहले, निम्नलिखित सभी को सत्यापित करें:
- एप्लिकेशन कनेक्शन एक सुपरयूज़र नहीं है, उसमें
BYPASSRLSकी कमी है, और वह कोई टेबल ओनर नहीं है जो सामान्य रूप से
पॉलिसी को बाईपास करता है; उपयुक्त होने पर FORCE ROW LEVEL SECURITY का उपयोग करें;
- प्रत्येक ट्रांज़ैक्शन टेनेंट सेट करता है और पूल रिटर्न से पहले इसे साफ़ करता है; गायब कॉन्टेक्स्ट डिफ़ॉल्ट टेनेंट चुनने के बजाय डिनाई करता है;
USINGविज़िबल पुरानी पंक्तियों को कवर करता है औरWITH CHECKइन्सर्ट या अपडेट की गई नई पंक्तियों को कवर करता है;- माइग्रेशन्स, बैकअप्स, वर्कर्स और सपोर्ट टूल्स अलग-अलग रोल्स और स्पष्ट प्रक्रियाओं का उपयोग करते हैं;
- पर्मिसिव पॉलिसियाँ डिफ़ॉल्ट रूप से
ORके साथ संयोजित होती हैं, इसलिए जोड़ी गई पॉलिसी गलती से एक्सेस को व्यापक नहीं बना सकती है;
जटिल सबक्वेरी पॉलिसियों की समवर्ती स्नैपशॉट्स और लागत के लिए भी समीक्षा की जाती है।
RLS प्रत्येक प्रोडक्ट संबंध को व्यक्त नहीं कर सकता है और ऑब्जेक्ट स्टोरेज या सर्च इंडेक्स की रक्षा नहीं कर सकता है जो डेटाबेस को बाईपास करता है। एप्लिकेशन पॉलिसी पूर्ण बिज़नेस सेमांटिक्स का स्वामित्व रखती है; RLS लीकेज को रोकता है यदि कोई एक क्वेरी टेनेंट स्कोप को छोड़ देती है। निरंतरता के लिए समान अनुमति मैट्रिक्स के विरुद्ध दोनों परतों का परीक्षण करें।
चरण 7: एरर्स, ऑडिट और फ़ाल्सीफ़ाइएबल (falsifiable) टेस्ट्स डिज़ाइन करें
क्रॉस-टेनेंट या इनविज़िबल ऑब्जेक्ट्स के लिए, यह परिदृश्य एक समान 404 और रिस्पॉन्स शेप देता है। एक डिनायल शीर्षक, टेनेंट का नाम, ओनर, वर्ज़न, फ़ाइल का आकार या एक विशिष्ट टाइमिंग संकेत वापस नहीं करता है। रेट लिमिटिंग इन्यूमरेशन और ऑडिट शोर को कम करती है, लेकिन सुरक्षा का दावा कभी भी इस बात पर निर्भर नहीं करता है कि अटैकर UUID का अनुमान लगाने में विफल रहता है।
एक्टर, विश्वसनीय टेनेंट, एक्शन, रिसोर्स ID का एक नियंत्रित प्रतिनिधित्व, निर्णय, कारण कोड, पॉलिसी वर्ज़न, सपोर्ट ग्रांट और ट्रेस ID को ऑडिट करें। डॉक्यूमेंट सामग्री, डाउनलोड कैपेबिलिटीज़, या पूर्ण JWTs को लॉग न करें। उपयोगी संकेतों में क्रॉस-टेनेंट डिनायल, एक ही सब्जेक्ट द्वारा कई गायब ऑब्जेक्ट्स की जाँच करना, पॉलिसी एरर्स, RLS डिनायल, रिवोकेशन के बाद रोकी गई जॉब्स और सपोर्ट-ग्रांट का उपयोग शामिल हैं।
टेस्ट मैट्रिक्स में कम से कम शामिल हैं:
- दो टेनेंट्स, प्रत्येक में ओनर, व्यूअर, एडिटर और एडमिन, साथ ही एक रिवोक किया गया यूज़र और टेम्पररी सपोर्ट ऑपरेटर;
- अपने, सेम-टेनेंट अनशेयर्ड, सीधे शेयर्ड, अन्य-टेनेंट के वैलिड UUID, और गैर-मौजूद UUID रिसोर्स;
- list, GET, PATCH, DELETE, शेयर, बल्क एक्सपोर्ट, GraphQL, डाउनलोड, कैशे हिट और वर्कर एक्ज़ीक्यूशन;
- पाथ्स, क्वेरीज़, JSON, एरेज़, नेस्टेड GraphQL वेरिएबल्स, स्टोरेज कीज़ और जॉब पेलोड्स में सब्स्टिट्यूशन;
- रीड्स पर कोई रिस्पॉन्स लीक नहीं और डिनायल पर कोई वर्ज़न, शेयर, फ़ाइल, मैसेज, सर्च-इंडेक्स या सक्सेस-ऑडिट में बदलाव नहीं;
- समवर्ती रिवोकेशन और अपडेट, एक पूल कनेक्शन का क्रमिक टेनेंट उपयोग, गायब RLS कॉन्टेक्स्ट,
गलत कॉन्फ़िगर किया गया एप्लिकेशन रोल और पुराना ऑथराइजेशन कैशे।
ऑथराइजेशन मैट्रिक्स से पॉजिटिव और नेगेटिव CI केसेस जेनरेट करें, और प्रत्येक नए एंडपॉइंट को अपने रिसोर्स और एक्शन को रजिस्टर करने की आवश्यकता रखें। स्कैनर्स कुछ इन्यूमरेबल पाथ्स ढूँढते हैं, लेकिन वे बिज़नेस ओनरशिप को नहीं जानते हैं। कई अकाउंट्स, ज्ञात वैलिड विदेशी ऑब्जेक्ट्स और साइड-इफेक्ट असर्शन्स यहाँ निर्णायक साक्ष्य हैं।
उच्च-गुणवत्ता वाला उदाहरण उत्तर
"मैं इस दोष को BOLA के रूप में वर्गीकृत करूँगा। JWT कॉलर की पहचान साबित करता है, जबकि API में टार्गेट डॉक्यूमेंट के लिए एक्शन-लेवल अनुमति का अभाव है। UUIDs इन्यूमरेशन की संभावना को कम करते हैं लेकिन ऑथराइजेशन निर्णय को नहीं बदलते हैं। मैं पहले एक subject, tenant, action, resource, context मैट्रिक्स को परिभाषित करूँगा और डिफ़ॉल्ट रूप से डिनाई करूँगा। एक यूज़र एक एक्टिव टेनेंट चुन सकता है, लेकिन सर्वर एक वेरिफाइड वर्तमान मेंबरशिप से टेनेंट कॉन्टेक्स्ट प्राप्त करता है।
डेटा लेयर अब बिज़नेस रूट्स के लिए ग्लोबल findById को एक्सपोज़ नहीं करती है। एक रीड पहले विश्वसनीय tenant_id + document_id द्वारा स्कोप तय करता है, फिर read, update, delete, share, या export के लिए रोल, ओनरशिप और शेयरिंग नियम लागू करता है। एक साधारण अपडेट एक ही सशर्त स्टेटमेंट में टेनेंट, ऑब्जेक्ट, एक्शन शर्तों और रिसोर्स वर्ज़न को ले जाता है। शून्य प्रभावित पंक्तियाँ हर साइड इफेक्ट को रोकती हैं। जटिल पॉलिसियाँ एक ट्रांज़ैक्शन में प्रासंगिक वर्ज़न्स को रखती हैं। कंपोजिट टेनेंट फॉरेन कीज़ क्रॉस-टेनेंट चाइल्ड संबंधों को रोकती हैं।
मैं उस मॉडल में हर बाईपास को शामिल करूँगा। बल्क एक्सपोर्ट हर ID को ऑथराइज करता है और यहाँ ऑल-ऑर-नथिंग है। कैशे कीज़ में टेनेंट शामिल होता है और कैशे हिट्स अभी भी पुन: ऑथराइज करते हैं। डाउनलोड लिंक्स जारी करने के समय download अनुमति की आवश्यकता होती है और वे ऑब्जेक्ट को एक छोटी एक्सपायरी से बाइंड करते हैं। जॉब्स एनक्यू और एक्ज़ीक्यूशन के समय चेक करती हैं ताकि एक्सपोर्ट से पहले रिवोकेशन प्रभावी हो जाए। RLS एक बैकस्टॉप है, लेकिन एप्लिकेशन रोल में BYPASSRLS और टेबल ओनरशिप का अभाव होना चाहिए, और पूल ट्रांज़ैक्शन कॉन्टेक्स्ट का टेनेंट लीकेज के लिए परीक्षण किया जाना चाहिए।
अंत में, मैं दो टेनेंट्स में मल्टी-रोल अकाउंट्स का उपयोग करूँगा और पाथ्स, JSON, बल्क लिस्ट्स और GraphQL में एक ज्ञात वैलिड विदेशी UUID रखूँगा। टेस्ट्स रीड, राइट, डिलीट, एक्सपोर्ट, डाउनलोड, कैशे और वर्कर पाथ्स को कवर करते हैं। प्रत्येक डिनायल एक गैर-प्रकटीकरण रिस्पॉन्स और कोई डेटाबेस-वर्ज़न, फ़ाइल, मैसेज या सर्च-इंडेक्स परिवर्तन न होने का दावा करता है। यह लॉगिन, एरर रिस्पॉन्स और साइड इफेक्ट्स को कवर करते हुए पाथ दर पाथ ऑब्जेक्ट-लेवल ऑथराइजेशन को साबित करता है।"
सामान्य गलतियाँ
- UUID, Base64, या एन्क्रिप्टेड IDs को समाधान मानना → IDs लॉग्स, शेयर्स या अन्य APIs के ज़रिए लीक होते हैं, और एक
वैलिड रेफरेंस अभी भी सीमा को पार करता है → **प्रत्येक रिक्वेस्ट पर सब्जेक्ट, टेनेंट, ऑब्जेक्ट और एक्शन को ऑथराइज करें; रैंडम IDs का उपयोग केवल डिफेंस-इन-डेप्थ के रूप में करें।**
- JWT वैलिडेशन के बाद किसी भी ID की अनुमति देना → ऑथेंटिकेशन सब्जेक्ट की पहचान करता है लेकिन कोई रिसोर्स अधिकार नहीं देता है →
वेरिफाइड मेंबरशिप से टेनेंट कॉन्टेक्स्ट बनाएँ और फिर ऑब्जेक्ट का निर्णय लें।
- कंट्रोलर्स में ग्लोबली लोड करना और हाथ से ओनर चेक लिखना → नए रूट्स, बल्क, कैशे और वर्कर्स इसे छोड़ देते हैं,
जबकि टीम शेयरिंग को गलत तरीके से डिनाई कर दिया जाता है → टेनेंट-स्कोप वाले डेटा एक्सेस और डिफ़ॉल्ट डिनाई के साथ केंद्रीय पॉलिसी को एक्सपोज़ करें।
- केवल GET का परीक्षण करना → PATCH, DELETE, एक्सपोर्ट, GraphQL और डाउनलोड्स अभी भी लीक हो सकते हैं या म्यूटेट कर सकते हैं → **एंट्री पॉइंट्स
और एक्शन्स के पार एक मल्टी-अकाउंट नेगेटिव मैट्रिक्स जेनरेट करें।**
- सफल बैच से अस्वीकृत IDs को फ़िल्टर करना → काउंट्स और सामग्री अस्तित्व का ओरैcle बन जाते हैं, और आंशिक
सफलता अस्पष्ट होती है → ऑल-ऑर-नथिंग या प्रति-आइटम सेमांटिक्स को पूर्व-परिभाषित करें और प्रत्येक ऑब्जेक्ट को ऑथराइज करें।
- यह मान लेना कि RLS स्वचालित सुरक्षा है → टेबल ओनर्स, सुपरयूज़र्स,
BYPASSRLS, गायब कॉन्टेक्स्ट और पर्मिसिव पॉलिसी
कंपोज़िशन आइसोलेशन को तोड़ सकते हैं → रोल्स, ट्रांज़ैक्शन कॉन्टेक्स्ट, USING/WITH CHECK और फ़ेलियर मोड्स को सत्यापित करें।
- केवल 403 या 404 का दावा करना → सिस्टम ने डिनायल से पहले डेटा लिख दिया हो, कोई मैसेज भेज दिया हो, या कोई फ़ाइल जेनरेट कर दी हो →
दावा करें कि प्रत्येक स्थायी और बाहरी साइड इफेक्ट अपरिवर्तित रहता है।
- जाँच के लिए पूर्ण ऑब्जेक्ट्स और टोकन्स को लॉग करना → सिक्योरिटी टेलीमेट्री एक और डेटा लीक बन जाती है → **न्यूनतम
पहचान, एक्शन, कारण और एक नियंत्रित रिसोर्स आइडेंटिफायर रिकॉर्ड करें।**
फ़ॉलो-अप प्रश्न और उत्तर
फ़ॉलो-अप 1: यदि UUIDv4 का अनुमान लगाना वास्तव में असंभव है, तो क्या ऑब्जेक्ट ऑथराइजेशन अभी भी आवश्यक है?
हाँ। रेफरेंस शेयर लिंक्स, ब्राउज़र हिस्ट्री, लॉग्स, नोटिफिकेशन्स, एनालिटिक्स, किसी अन्य API या किसी गलत निर्देशित मैसेज के ज़रिए लीक होते हैं। UUIDs ब्लाइंड इन्यूमरेशन को कम करते हैं; वे किसी ओनर, टेनेंट, एक्शन या एक्सपायरी को व्यक्त नहीं करते हैं। एक टेस्ट में अटैकर अकाउंट को एक ज्ञात वैलिड विदेशी UUID दें। सफल एक्सेस तुरंत गायब ऑथराइजेशन को साबित करता है।
फ़ॉलो-अप 2: क्या प्रत्येक क्रॉस-टेनेंट ऑब्जेक्ट के लिए 404 लौटाने से डिबगिंग बहुत कठिन हो जाती है?
बाहरी रिस्पॉन्स एक समान हो सकते हैं जबकि आंतरिक ऑडिट स्थिर कारण रखता है जैसे RESOURCE_NOT_VISIBLE, ACTION_DENIED, या TENANT_CONTEXT_INVALID। ऑपरेटर्स नियंत्रित लॉग्स और एक ट्रेस ID के माध्यम से जाँच करते हैं; कॉलर्स को यह पता नहीं चलता कि कोई ऑब्जेक्ट मौजूद है या नहीं। यदि सेम-टेनेंट सहयोग के लिए "कोई एडिट अनुमति नहीं" की आवश्यकता है, तो एक सुसंगत API कॉन्ट्रैक्ट के तहत ऑब्जेक्ट के विज़िबल होने की पुष्टि करने के बाद ही 403 लौटाएँ।
फ़ॉलो-अप 3: जब किसी यूज़र को टेनेंट से हटा दिया जाता है तो कतारबद्ध (queued) एक्सपोर्ट्स का क्या होता है?
सफल सबमिशन स्थायी रीड अधिकार नहीं बनाता है। निष्पादन से पहले, प्रत्येक रिसोर्स के लिए मेंबरशिप और export अनुमति को फिर से लोड करें। रिवोकेशन के बाद, जॉब को अस्वीकार करें, टेम्पररी फ़ाइलों को डिलीट करें और कोई डाउनलोड URL जारी न करें। यदि अनुपालन के लिए सबमिशन के समय अधिकार फ़्रीज़ करने की आवश्यकता है, तो पुराने JWT रोल्स को चुपचाप बनाए रखने के बजाय स्कोप, अप्रूवर और एक्सपायरी के साथ एक स्पष्ट अल्पकालिक ऑथराइजेशन स्नैपशॉट बनाएँ।
फ़ॉलो-अप 4: यदि प्रत्येक एप्लिकेशन क्वेरी में पहले से ही tenant_id शामिल है, तो RLS क्या जोड़ता है?
यह एक नई क्वेरी को रोक सकता है जो प्रेडिकेट को छोड़ देती है और कुछ डायरेक्ट डेटाबेस पाथ्स को भी, जिससे एक चूक के प्रभाव का दायरा (blast radius) कम हो जाता है। यह पूल कॉन्टेक्स्ट, रोल, माइग्रेशन और पॉलिसी-मेंटेनेंस की लागत भी जोड़ता है और सर्च, कैशे या ऑब्जेक्ट स्टोरेज की रक्षा नहीं कर सकता है। अत्यधिक संवेदनशील शेयर्ड टेबल्स दोनों परतों के लिए अच्छे उम्मीदवार हैं। पहले यह साबित करें कि एप्लिकेशन रोल RLS को बाईपास नहीं कर सकता है, गायब टेनेंट कॉन्टेक्स्ट डिनाई करता है, पूल कॉन्टेक्स्ट लीक नहीं होता है, और दोनों परतें समान मैट्रिक्स से मेल खाती हैं।
फ़ॉलो-अप 5: सपोर्ट इंजीनियर्स को टेम्पररी ग्राहक-डॉक्यूमेंट एक्सेस की आवश्यकता होती है। आप एक स्थायी बैकडोर से कैसे बचते हैं?
एक टिकट, टार्गेट टेनेंट, अनुमत एक्शन्स, अप्रूवर, छोटी एक्सपायरी और कारण से बंधी अलग जस्ट-इन-टाइम सपोर्ट ऑथराइजेशन बनाएँ। संवेदनशील एक्शन्स के लिए दो-व्यक्ति अनुमोदन (two-person approval) की आवश्यकता हो सकती है। सपोर्ट और सामान्य एंडपॉइंट्स को अलग करें, एक प्रमुख सेशन स्थिति दिखाएं, बल्क डाउनलोड पर रोक लगाएं और प्रत्येक ऑब्जेक्ट एक्सेस का ऑडिट करें। एक्सपायरी एक्सेस को तुरंत रिवोक करती है, और उपयोग की समय-समय पर समीक्षा की जाती है। सामान्य एप्लिकेशन रोल्स और सर्विस टोकन्स को कोई क्रॉस-टेनेंट अनुमति नहीं मिलती है।