Headers as Bags
HTTP लॉगिंग फ्रेमवर्क रिक्वेस्ट हेडर्स को की-वैल्यू पेयर्स के बैग के रूप में मानते हैं। लॉगिंग API पूरा बैग एक्सपोज़ करता है। ऑपरेटर्स डीबगिंग के लिए हेडर लॉगिंग सक्षम करते हैं: जब कोई रिक्वेस्ट फेल होती है, हेडर्स कहानी बताते हैं। कोई बिल्ट-इन डेनिलिस्ट नहीं। डॉक्यूमेंटेशन में कोई क्रेडेंशियल फ़िल्टरिंग नहीं। पूरा हेडर्स डिस्क पर।
एक सामान्य रिक्वेस्ट में क्रेडेंशियल हेडर्स:
- Authorization: Bearer eyJhbGciOiJIUzI1NiJ9... (JWT या OAuth टोकन)
- Cookie: session=abc123; auth=xyz789
- X-API-Key: sk-live-abc123...
- X-Auth-Token: ghp_abc123... (GitHub personal access token pattern)
ये मान अनुरोध को प्रमाणित करते हैं। यदि किसी लॉग फ़ाइल में लिखे जाएँ, तो वे किसी भी अनुरोध को प्रमाणित कर सकते हैं।
क्रेडेंशियल पाइपलाइन
लॉग फ़ाइल में लिखा गया क्रेडेंशियल एक जगह पर नहीं रहता। यह यात्रा करता है:
1. वेब सर्वर /var/log/nginx/access.log में लिखता है
2. लॉग रोटेशन एजेंट (logrotate) इसे /var/log/nginx/access.log.1 में कॉपी करता है
3. लॉग शिपर (Fluentd, Filebeat, Logstash) पढ़ता है और एग्रीगेटर को भेजता है
4. लॉग एग्रीगेटर (Elasticsearch, Splunk, Datadog) इंडेक्स करता है और स्टोर करता है
5. डिफ़ॉल्ट पॉलिसी के तहत 30-90 दिनों तक रखा जाता है
क्रेडेंशियल पाँचों स्थानों पर एक साथ मौजूद रहता है। सेशन टोकन को रिवोक करने से लॉग एग्रीगेटर से क्रेडेंशियल हटता नहीं है। यह पूरे रिटेंशन विंडो तक लॉग एक्सेस वाले किसी भी व्यक्ति के लिए सर्चेबल, एक्सपोर्टेबल और एक्सेसिबल बना रहता है।
एक्सपोज़र विंडो
मेमोरी में क्रेडेंशियल के लिए एक्सपोज़र विंडो: max(session duration, process lifetime)। सेशन: घंटों से दिनों तक। प्रोसेस: घंटों से हफ्तों तक।
लॉग में क्रेडेंशियल के लिए एक्सपोज़र विंडो: max(session duration, log retention)। सेशन: घंटों से दिनों तक। रिटेंशन: 30-90 दिन।
मेमोरी से चुराया गया क्रेडेंशियल प्राप्त करने के लिए अटैकर को सेशन विंडो के दौरान मौजूद होना पड़ता था। लॉग से चुराया गया क्रेडेंशियल केवल लॉग एग्रीगेटर तक एक्सेस की आवश्यकता रखता है, जो रिटेंशन पीरियड के लिए रेट्रोएक्टिव रूप से उपलब्ध रहता है।
MOAD-0003 vs MOAD-0004
MOAD-0003 (Leaked Context): मेमोरी में मौजूद क्रेडेंशियल गलत रिक्वेस्ट हैंडलर में लीक हो जाता है। केवल प्रोसेस विंडो के दौरान, थ्रेड पूल के माध्यम से एक्सेसिबल। Ephemeral. [BLOCK_TYPE persistence_problem/headers_as_bags]
MOAD-0004 (Logged Secret): डिस्क पर मौजूद क्रेडेंशियल लॉग रोटेशन, लॉग शिपिंग और लॉग एग्रीगेशन के बाद भी बना रहता है। लॉग एक्सेस वाले किसी भी व्यक्ति को रेट्रोएक्टिव रूप से 30-90 दिनों तक एक्सेसिबल। Persistent. [BLOCK_TYPE persistence_problem/headers_as_bags]
संरचनात्मक अंतर: ephemeral vs persistent. फिक्स एक अलग लेयर पर काम करता है। [BLOCK_TYPE persistence_problem/persistence_question]
Ephemeral vs Persistent [BLOCK_TYPE persistence_problem/persistence_question]
Ephemeral/persistent अंतर रिस्क सरफेस, फिक्स लेयर और इंसिडेंट रिस्पॉन्स आवश्यकताओं को निर्धारित करता है। [BLOCK_TYPE persistence_problem/persistence_question]
Credential Denylist at the Serialization Layer
समाधान: सीरियलाइज़ेशन लेयर पर एक क्रेडेंशियल डेनिलिस्ट। किसी भी हेडर वैल्यू के लॉग आउटपुट तक पहुँचने से पहले, हेडर नाम की डेनिलिस्ट से तुलना करें। वैल्यू को [REDACTED] से बदल दें।
CREDENTIAL_HEADERS = {
'authorization',
'cookie',
'x-api-key',
[BLOCK_TYPE CONTENT denylist_fix/how_it_works]
'x-auth-token',
[BLOCK_TYPE CONTENT denylist_fix/how_it_works]
'x-csrf-token',
[BLOCK_TYPE CONTENT denylist_fix/how_it_works]
'proxy-authorization',
[BLOCK_TYPE CONTENT denylist_fix/how_it_works]
}
[BLOCK_TYPE CONTENT denylist_fix/how_it_works]
[BLOCK_TYPE CONTENT denylist_fix/how_it_works]
def sanitize_headers(headers: dict) -> dict:
[BLOCK_TYPE CONTENT denylist_fix/how_it_works]
return {
k: '[REDACTED]' if k.lower() in CREDENTIAL_HEADERS else v
for k, v in headers.items()
}
डेनिलिस्ट सीरियलाइज़ेशन लेयर पर होना चाहिए, न कि लॉग क्वेरी लेयर पर। लॉग क्वेरी रिडैक्शन: क्रेडेंशियल डिस्क पर पहुँचने के बाद लागू होता है; कच्चा मान अभी भी मौजूद रहता है, केवल प्रदर्शन से छिपा होता है। सीरियलाइज़ेशन लेयर रिडैक्शन: क्रेडेंशियल कभी भी डिस्क तक नहीं पहुँचता। कच्चा मान कभी भी लॉग फ़ाइल, लॉग शिपर या लॉग एग्रीगेटर में प्रवेश नहीं करता।
डेनिलिस्ट का परीक्षण
तीन परीक्षण पैटर्न:
- सकारात्मक: Authorization: Bearer token123 वाले अनुरोध से लॉग एंट्री Authorization: [REDACTED] उत्पन्न होती है
- नकारात्मक: Content-Type: application/json वाले अनुरोध से लॉग एंट्री में मूल मान बरकरार रहता है
- केस-असंवेदनशील: AUTHORIZATION: Bearer token123 भी [REDACTED] उत्पन्न करता है (HTTP हेडर नाम केस-असंवेदनशील होते हैं)
डेनिलिस्ट को रखरखाव की आवश्यकता होती है: नए क्रेडेंशियल हेडर पैटर्न (जैसे कस्टम X-Service-Auth हेडर) को स्पष्ट रूप से जोड़ना पड़ता है। यह फिक्स संरचनात्मक है लेकिन स्वयं-रखरखाव योग्य नहीं है।
डेनिलिस्ट लागू करें
एक टीम प्रोडक्शन इंसीडेंट को डीबग करने के लिए Nginx एक्सेस लॉग फॉर्मेट को कॉन्फ़िगर करती है जिसमें सभी रिक्वेस्ट हेडर शामिल हों। कॉन्फ़िगरेशन:
log_format debug_format '$remote_addr - $request - $http_authorization - $http_cookie';
access_log /var/log/nginx/debug.log debug_format;
वे घटना को हल करते हैं और डीबग कॉन्फ़िगरेशन को हटाने का इरादा रखते हैं, लेकिन अगले डिप्लॉयमेंट चक्र (7 दिन बाद) से पहले बदलाव प्रोडक्शन तक नहीं पहुँच पाता।