
उस भेद्यता को खोजें जिसे पकड़ने के लिए आपके टेस्ट कभी लिखे ही नहीं गए थे। ReGrade का एक डेमो जो CVE-2023-5968 को मॉडल करता है: किसी ऐप की उसी से तुलना करके पासवर्ड-हैश लीक को पकड़ें।
ReGrade के साथ ज़ीरो-डे खोज का एक व्यावहारिक डेमो। आप एक साधारण टेस्ट सूट को ReGrade पर इंगित करेंगे, उसे एक छोटी सेवा के विरुद्ध रिकॉर्ड करेंगे, उसे उसी सेवा की दूसरी कॉपी के विरुद्ध रीप्ले करेंगे, और Claude Code + ReGrade MCP टूल्स का उपयोग करके पासवर्ड-हैश लीक सतह पर लाएँगे — एक ऐसी भेद्यता जिसे खोजने के लिए कोई टेस्ट नहीं लिखा गया था।
यह एक वास्तविक बग का मॉडल है: CVE-2023-5968, जहाँ एक सहयोग प्लेटफ़ॉर्म का यूज़रनेम-अपडेट एंडपॉइंट पूरा यूज़र ऑब्जेक्ट bcrypt पासवर्ड हैश सहित लौटाता था। यह 2017 में शिप हुआ और 7 वर्षों के टेस्ट, समीक्षाओं और ऑडिट से बच गया। (Curtail का लेख.)
ट्विस्ट यह है: कोई v2 नहीं है। आप ऐप की तुलना उसी से करते हैं। एक नया इंस्टेंस अपने
पासवर्ड को अलग-अलग bcrypt सॉल्ट के साथ हैश करता है, इसलिए लीक हुए हैश के मान दोनों
कॉपियों के बीच भिन्न होते हैं — और ReGrade उसी एंट्रॉपी को फ़्लैग करता है। भेद्यता उस कोड में निष्क्रिय है
जिसे आप पहले ही शिप कर चुके हैं; इसे खोजने के लिए किसी वर्जन परिवर्तन की आवश्यकता नहीं है।
regrade सेंसर को से इंस्टॉल करें, और
(या ) सेट करें।REGRADE_API_KEY~/.regrade/keyclaude plugin marketplace add https://app.regrade.curtail.com/downloads/latest/marketplace.json
फिर claude plugin install regrade@regrade --scope user, और इसे एक बार कनेक्ट करें (/mcp,
अपनी कुंजी के समान खाते में साइन इन करके)।यूज़र और चैनल वाला एक छोटा "टीम-चैट" API (app/store.py)। Docker Compose दो समान कॉपियाँ
चलाता है — समान इमेज, समान कोड, कोई वर्जन फ़्लैग नहीं:
http://localhost:8001 पर — आप इसके विरुद्ध रिकॉर्ड करते हैं।http://localhost:8002 पर — आप इसके विरुद्ध रीप्ले करते हैं।एक एंडपॉइंट में एक छुपाई गई खामी है:
| Endpoint | Behavior |
|---|---|
GET /users/<id> | Sanitized — पासवर्ड कभी नहीं लौटाता। साफ़ बेसलाइन। |
PATCH /users/<id> (rename) | बग — पूरा यूज़र ऑब्जेक्ट bcrypt password हैश सहित लौटाता है। एक गायब sanitize() कॉल, बिल्कुल CVE-2023-5968 की तरह। |
पासवर्ड बूट के समय bcrypt-हैश होते हैं, इसलिए instance-a और instance-b एक ही यूज़र के लिए अलग-अलग हैश रखते हैं।
git clone https://github.com/Curtail-Inc/hello-ReGrade-security
cd hello-ReGrade-security
docker compose up -d --build
traffic/test_api.py एक सामान्य फ़ंक्शनल टेस्ट सूट है: लॉगिन, यूज़र पढ़ना, यूज़र का नाम बदलना,
चैनल सूचीबद्ध करना। यह CRUD व्यवहार को सत्यापित करता है और कोई सुरक्षा अभिकथन नहीं बनाता —
यह कभी जाँच नहीं करता कि password लीक होता है या नहीं। (ऐसा क्यों करे? किसी को नहीं पता था कि बग मौजूद है।)
instance-a के सामने सेंसर प्रॉक्सी शुरू करें:
regrade proxy --target http://localhost:8001 --port 19870
दूसरे टर्मिनल में, वही टेस्ट सूट चलाएँ — बस BASE_URL को प्रॉक्सी पर इंगित करें। यही
एकमात्र बदलाव है:
BASE_URL=http://localhost:19870 python -m pytest traffic/test_api.py
सभी टेस्ट बिना किसी बदलाव के पास हो जाते हैं। प्रॉक्सी रोकें (Ctrl-C); रिकॉर्डिंग अपलोड होकर एक
Recording ID: <uuid> प्रिंट करती है — इसे नोट कर लें।
regrade replay --rec-id <RECORDING_ID> --target http://localhost:8002
दोनों ओर समान कोड — एकमात्र अंतर वे मान हैं जो एक नया इंस्टेंस उत्पन्न करता है।
इस रिपो को Claude Code में खोलें और उसे रीप्ले के माध्यम से आपका मार्गदर्शन करने के लिए कहें। इस रिपो की
CLAUDE.md द्वारा निर्देशित होकर, यह:
summarize_deltas चलाएगा → कई डेल्टा: लॉगिन token, चैनल created_at टाइमस्टैम्प,
और — चुपचाप उनके बीच — $.password।$.token के लिए create_id_mapping (एक गतिशील ID, हटाने योग्य शोर नहीं),$.channels[*].created_at के लिए create_filter_rule DROP (एक प्रति-बूट टाइमस्टैम्प),apply_profile_to_replay, फिर query_deltas(unlabeled_only=true) — तब तक दोहराएँ जब तक केवल एक
डेल्टा शेष न रह जाए।$.password है — एक रिस्पॉन्स बॉडी में bcrypt हैश।
एक CVE-श्रेणी का लीक, जो शून्य पूर्व ज्ञान और शून्य सुरक्षा अभिकथनों के साथ पाया गया।सत्र टोकन और पासवर्ड हैश दोनों दोनों रनों के बीच भिन्न होते हैं — दोनों उच्च-एंट्रॉपी स्ट्रिंग हैं जो हर बार बदलती हैं। एक वैध शोर है जिसे आप मैप करते हैं; दूसरा उल्लंघन (breach) है। आप उन्हें "यह बदल गया" कहकर अलग नहीं बता सकते — आपको देखना होगा कि क्या बदला। हर उच्च-एंट्रॉपी फ़ील्ड को शोर के रूप में फ़िल्टर कर देते, तो आपने भेद्यता छिपा दी होती।
यही सबक है: ReGrade अपेक्षाओं को मान्य नहीं करता, यह व्यवहार की तुलना करता है — इसलिए यह उन बगों को सतह पर ला सकता है जिनके लिए किसी ने टेस्ट लिखने के बारे में नहीं सोचा।
app/store.py एक फ़ाइल है। GET पथ sanitize() को कॉल करते हैं; PATCH पथ ऐसा करना भूल जाता है।
इसे ReGrade के साथ खोजने के बाद देखें — मुद्दा यह है कि ReGrade ने इसे अकेले ट्रैफ़िक
से, ऐप की उसकी स्वयं से तुलना करके पकड़ा।
Apache-2.0.