एक बदला हुआ ID: कैसे एक AI पेंटेस्ट पूरे अकाउंट टेकओवर तक पहुँचा
यह एक वास्तविक एंगेजमेंट है, जिसे Sintropyc के स्वायत्त AI पेंटेस्टिंग एजेंट ने आद्योपांत चलाया। यह एक गणनीय ऑब्जेक्ट ID से शुरू हुआ और निजी एडमिन डैशबोर्ड तक पहुँचा — और रास्ते में एजेंट ने अपने पहले निष्कर्ष को ख़ुद ही ख़ारिज कर दिया, यह मानते हुए कि वह संभवतः ग़लत पॉज़िटिव है। सभी पहचान-योग्य विवरण गुमनाम कर दिए गए हैं; ऐप का परीक्षण मालिक की अनुमति से किया गया।
एक पंक्ति में सार
एक स्वायत्त AI एजेंट ने एक ई-कॉमर्स SaaS का परीक्षण ठीक वैसे किया जैसे कोई वास्तविक हमलावर करता। उसने पाया कि केवल एक पूर्णांक बदलकर वह दूसरे सदस्यों की निजी प्रोफ़ाइल पढ़ सकता है, उस निष्कर्ष को संभावित ग़लत पॉज़िटिव मानकर ख़ारिज कर दिया, वास्तव में अलग-अलग अकाउंट पर उसे फिर से सिद्ध किया, और फिर ऐप को एडमिन तक पूरी तरह चला गया — साठ सेकंड पहले बनाए गए एक ग्राहक के रूप में निजी रेवेन्यू डैशबोर्ड पढ़ लिया। हर कदम एक सिद्ध प्रभाव है, स्कैनर का “संभव” नहीं।
परीक्षण ऐप मालिक की अनुमति से, डिफ़ॉल्ट रूप से केवल-पढ़ने के मोड में, एक पृथक सैंडबॉक्स में, सुरक्षित एवं प्रतिवर्ती पेलोड के साथ किया गया। लक्ष्य, उसका डोमेन, वास्तविक उपयोगकर्ता और कोई भी रहस्य गुमनाम या हटा दिए गए हैं — यहाँ कुछ भी किसी वास्तविक व्यक्ति, क्रेडेंशियल या सिस्टम की ओर इशारा नहीं करता।
यह बग बार-बार क्यों जीतता है
Broken Object-Level Authorization — BOLA, क्लासिक IDOR का API-युग वाला सगा — OWASP API Security Top 10 में पहले स्थान पर है। यह बग साधारण है और हर जगह है: GET /api/members/{id} जैसा एंडपॉइंट आपके भेजे किसी भी id के लिए ऑब्जेक्ट लौटा देता है, बिना यह जाँचे कि आपको उसे देखने की अनुमति है या नहीं। नंबर बदलिए, किसी और का डेटा पढ़ लीजिए।
स्कैनर इसमें कमज़ोर हैं। स्कैनर देखता है कि GET /api/members/42 ने 200 OK लौटाया और आगे बढ़ जाता है — 200 तो लौटना ही चाहिए। रिकॉर्ड आपका है या किसी अजनबी का — यह पहचान और व्यावसायिक संदर्भ का प्रश्न है, HTTP स्टेटस कोड का नहीं। इसीलिए यह वह श्रेणी है जिसे मानव परीक्षक सबसे अधिक पकड़ते हैं और स्वचालित उपकरण सबसे अधिक चूकते हैं — और यही वह श्रेणी है जिसे हमारा एजेंट सबसे अधिक सिद्ध करता है।
संकेत: एक बदला हुआ ID
लक्ष्य एक स्टोरफ़्रंट SaaS था — एक सिंगल-पेज ऐप जो JSON API से बात करता है। एजेंट ने API का नक्शा बनाया और दो बातें देखीं जो ऑथराइज़ेशन बग के लिए मायने रखती हैं: सदस्य ID क्रमिक पूर्णांक थे, और सदस्य ऑब्जेक्ट में एक पासवर्ड-रिकवरी हिंट था — एक निजी फ़ील्ड जो कभी भी मालिक के अपने सेशन से बाहर नहीं जाना चाहिए।
तो उसने Account A बनाया और एक सरल सवाल पूछा: A के रूप में, क्या मैं सदस्य 1 को पढ़ सकता हूँ? और 10 को? दोनों ने पूरी प्रोफ़ाइल लौटाई, हिंट फ़ील्ड सहित। काग़ज़ पर: पाठ्यपुस्तक जैसा IDOR। एक स्कैनर या उतावला परीक्षक 200 का स्क्रीनशॉट लेकर उसे HIGH लिख देता।
हमारे एजेंट ने ऐसा नहीं किया।
जो ग़लत पॉज़िटिव एजेंट ने फेंक दिया
कुछ भी दर्ज करने से पहले, एजेंट ने वही मानक लगाया जिस पर वह हर ऑथराइज़ेशन दावे को कसता है: क्रॉस-अकाउंट रीड तभी वास्तविक उल्लंघन है जब दोनों पहचानें सचमुच अलग मालिक हों और किसी निजी संसाधन तक कोई वैध साझा पहुँच न हो। और उसने अपने ही साक्ष्य में छेद पकड़ा — कई ऐप में, स्वयं-पंजीकृत अकाउंट चुपचाप उसी डिफ़ॉल्ट वर्कस्पेस में आ जाते हैं। यदि A और “पीड़ित” एक ही वर्कस्पेस साझा करते हैं, तो A का वह रिकॉर्ड पढ़ना सीमा-उल्लंघन नहीं, बल्कि अधिकृत साझा पहुँच है। एक वास्तविक भेद्यता और एक सामान्य फ़ीचर रिस्पॉन्स में बाइट-दर-बाइट एक जैसे दिख सकते हैं।
इसलिए एजेंट ने अपने ही दावे को घटाया और ख़ारिज किया, और ख़ुद को कठिन काम दिया: ऐसे मालिकों पर सिद्ध करो जो स्पष्ट रूप से अलग हों। एक्सेस-कंट्रोल परीक्षण में यही ग़लत पॉज़िटिव का सबसे बड़ा स्रोत है।
उसने एक दूसरा, स्वतंत्र अकाउंट बनाया, पुष्टि की कि दोनों बिना साझा सदस्यता वाले अलग मालिक हैं, और क्रॉस-रीड फिर चलाया। वह टिका रहा। केवल URL में एक पूर्णांक बदलकर एक अकाउंट दूसरे मालिक की निजी प्रोफ़ाइल पढ़ सका। अब यह एक निष्कर्ष था — गंभीरता ठीक उतनी जितनी दिखाई गई।
पढ़ने से पूरे स्टोर तक
एक रीड-प्रिमिटिव बुरा है। इसे टेकओवर बनाया अगले सवाल ने: यदि सर्वर यह नहीं जाँचता कि कौन पढ़ सकता है, तो क्या वह जाँचता है कि कौन लिख सकता है — और क्या लिख सकता है? नहीं जाँचता था।
रजिस्ट्रेशन और प्रोफ़ाइल-अपडेट एंडपॉइंट क्लाइंट से भेजा गया role फ़ील्ड स्वीकार कर उसे ज्यों-का-त्यों सहेज लेते थे। एजेंट ने एक नया ग्राहक बनाया और अपनी भूमिका admin कर दी। यह सिद्ध करने के लिए कि यह वृद्धि वास्तविक है, उसने विशेषाधिकार का उपयोग किया: कुछ मिनट पुराने ग्राहक के रूप में उसने निजी एडमिन डैशबोर्ड खोला — कुल सदस्य और रेवेन्यू — और 200 OK पाया। फिर उसने यही चाल उपयोगकर्ताओं के बीच दोहराई: एक ग्राहक ने दूसरे ग्राहक की भूमिका बदल दी। राइट-पाथ पर भी न स्वामित्व-जाँच, न भूमिका-जाँच। हर बदलाव सौम्य, स्वतः-पूर्ववत होने वाले मार्करों से वापस कर दिया गया।
वे दरवाज़े जिन पर ताला ही नहीं था
एजेंट ने बिना चाबी वाले सामने के दरवाज़े भी आज़माए। कई /admin/* एंडपॉइंट और एक उपयोगकर्ता-सूची एंडपॉइंट ने पूर्णतः अप्रमाणित अनुरोध को डेटा लौटाया: स्टोर कॉन्फ़िगरेशन, रेवेन्यू डैशबोर्ड, और हर सदस्य का ईमेल व पूरा नाम। न टोकन, न सेशन — बस एक GET। उसने क्लासिक टोकन दोष भी पाया: सर्वर alg: none वाले JWT स्वीकार कर जाली दावों पर भरोसा करता था। जहाँ हस्ताक्षर-रहस्य प्रत्यक्ष रूप से नहीं देखा जा सका, एजेंट ने वैसा ही कहा और उस भाग को अनुमानित बताया, सिद्ध नहीं।
कैसे सुनिश्चित करें कि आपका ऐप ऐसा न करे
ये फ़िक्स दिखावटी नहीं हैं और काम करते हैं:
- हर ऑब्जेक्ट-एक्सेस को सर्वर-साइड पर, डिफ़ॉल्ट-डिनाई के साथ अधिकृत करें। हर
/{id}रूट पर जाँचें कि कॉलर उसी विशिष्ट ऑब्जेक्ट को देख या बदल सकता है। - क्लाइंट इनपुट को कभी विशेषाधिकार-फ़ील्ड से न जोड़ें। लिखने-योग्य फ़ील्ड को allow-list करें;
role,tier,ownerसर्वर द्वारा admin-only पथों से सेट हों। - ऑथराइज़ेशन को “मालिक बनाम मालिक” मानें। दो सचमुच अलग अकाउंट से परीक्षण करें।
- टोकन परत ठीक करें।
alg: noneअस्वीकारें, एल्गोरिद्म फ़िक्स करें, हस्ताक्षर सत्यापित करें, लीक हुए रहस्य बदलें। - हर एंडपॉइंट को तब तक सार्वजनिक मानें जब तक ऑथराइज़ेशन सिद्ध न हो — ख़ासकर
/adminऔर/internal।
बात बग की नहीं — प्रमाण की है
यहाँ हर निष्कर्ष प्रभाव से सिद्ध हुआ, किसी सिग्नेचर से दावे के रूप में नहीं। एक लौटाया गया पराया रिकॉर्ड। एक भूमिका-परिवर्तन जो टिका और दरवाज़ा खोल गया। एक ऐसे डेटा पर अप्रमाणित 200 जिसे सेशन चाहिए था। और जब साक्ष्य उस मानक तक नहीं पहुँचा, एजेंट ने वैसा ही कहा और या तो फिर सिद्ध किया या दावे को सीमित किया। प्रमाण, अनुमान नहीं। गंभीरता कभी उससे अधिक नहीं जितना वास्तव में दिखाया गया।