कॉन्टेंट की सुरक्षा के बारे में नीति

वेब के सुरक्षा मॉडल को एक ही ऑरिजिन से जुड़ी नीति में रूट किया गया है. https://mybank.com के कोड के पास सिर्फ़ https://mybank.com के डेटा का ऐक्सेस होना चाहिए. साथ ही, https://evil.example.com को कभी भी ऐक्सेस करने की अनुमति नहीं दी जानी चाहिए. हर ऑरिजिन को वेब के बाकी हिस्सों से अलग रखा जाता है. इससे डेवलपर को एक सुरक्षित सैंडबॉक्स बनाने और गेम खेलने की सुविधा मिलती है. सैद्धांतिक रूप से, यह पूरी तरह से बहुत ही शानदार है. व्यवहार में, हमलावरों ने सिस्टम को पलटने के लिए चतुर तरीके खोज लिए हैं.

क्रॉस-साइट स्क्रिप्टिंग (XSS) हमले, उदाहरण के लिए, किसी साइट पर अपनी पसंद के कॉन्टेंट के साथ नुकसान पहुंचाने वाला कोड डिलीवर करने का झांसा देकर, उसी ऑरिजिन नीति से बचने की कोशिश करते हैं. यह एक बड़ी समस्या है, क्योंकि ब्राउज़र उस पेज पर दिखने वाले सभी कोड को भरोसेमंद मानते हैं. XSS चीट शीट एक पुराना लेकिन पुराना क्रॉस-सेक्शन है. इसमें उन तरीकों का इस्तेमाल किया जाता है जिनका इस्तेमाल करके कोई हमलावर, नुकसान पहुंचाने वाले कोड डालकर इस भरोसे का उल्लंघन कर सकता है. अगर कोई हमलावर कोई भी कोड डाल देता है, तो इसका मतलब है कि उपयोगकर्ता के सेशन के डेटा के साथ छेड़छाड़ की गई है. साथ ही, जिस जानकारी को गुप्त रखा जाना चाहिए उसे The Bad Guys से बाहर निकाल दिया जाता है. अगर मुमकिन हो, तो हम उसे ठीक करना चाहेंगे.

इस खास जानकारी में, सुरक्षा के उस तरीके को हाइलाइट किया गया है जिससे आधुनिक ब्राउज़र में XSS हमलों के जोखिम और असर को काफ़ी हद तक कम किया जा सकता है: कॉन्टेंट की सुरक्षा के बारे में नीति (सीएसपी).

बहुत ज़्यादा शब्द हैं, पढ़ा नहीं गया

  • अनुमति वाले डोमेन की सूची का इस्तेमाल करके, क्लाइंट को बताएं कि आपके कारोबार के लिए किस तरह के विज्ञापन दिखाए जा सकते हैं और किस तरह के नहीं.
  • जानें कि कौनसे डायरेक्टिव उपलब्ध हैं.
  • उनके द्वारा लिए जाने वाले कीवर्ड जानें.
  • इनलाइन कोड और eval() को नुकसान पहुंचाने वाला माना जाता है.
  • नीति के उल्लंघन लागू करने से पहले अपने सर्वर को उनकी रिपोर्ट करें.

सोर्स की अनुमति वाली सूची

XSS हमलों का फ़ायदा उठाने वाली समस्या ब्राउज़र की उस स्क्रिप्ट के बीच अंतर करने में असमर्थता है, जो आपके ऐप्लिकेशन का हिस्सा है और स्क्रिप्ट जो किसी तृतीय-पक्ष द्वारा नुकसान पहुंचाने के इरादे से डाली गई है. उदाहरण के लिए, इस पेज पर सबसे नीचे मौजूद Google का +1 बटन, इस पेज के ऑरिजिन के हिसाब से https://apis.google.com/js/plusone.js से मिले कोड को लोड और लागू करता है. हमें उस कोड पर भरोसा है, लेकिन हम यह उम्मीद नहीं कर सकते कि ब्राउज़र खुद ही पता लगा पाए कि apis.google.com का कोड शानदार है, जबकि apis.evil.example.com से मिला कोड ऐसा हो सकता है. ब्राउज़र, सोर्स पर ध्यान दिए बिना, पेज के लिए अनुरोध किए गए किसी भी कोड को अच्छी तरह डाउनलोड और लागू करता है.

सर्वर से मिलने वाली हर चीज़ पर भरोसा करने के बजाय, सीएसपी Content-Security-Policy एचटीटीपी हेडर के बारे में जानकारी देता है. इसकी मदद से, भरोसेमंद कॉन्टेंट के सोर्स की एक सूची बनाई जा सकती है. साथ ही, ब्राउज़र को सिर्फ़ उन सोर्स के संसाधनों को इस्तेमाल या रेंडर करने के निर्देश दिए जाते हैं. अगर कोई हमलावर स्क्रिप्ट इंजेक्ट करने के लिए कोई छेद ढूंढ लेता है, तो भी स्क्रिप्ट, अनुमति वाली सूची से मैच नहीं करेगी. इसलिए, स्क्रिप्ट को लागू नहीं किया जाएगा.

हम apis.google.com को मान्य कोड डिलीवर करने के लिए भरोसा करते हैं और हम भी खुद पर भरोसा करते हैं. इसलिए, अब हम एक ऐसी नीति तय करते हैं जो स्क्रिप्ट को सिर्फ़ तब काम करने की अनुमति देती है, जब वह उन दो सोर्स से आता है:

Content-Security-Policy: script-src 'self' https://apis.google.com

आसान है, है न? जैसा कि आपने अंदाज़ा लगा ही लिया होगा कि script-src एक ऐसा डायरेक्टिव है जो किसी खास पेज के लिए, स्क्रिप्ट से जुड़े खास अधिकारों के सेट को कंट्रोल करता है. हमने 'self' को स्क्रिप्ट के एक मान्य सोर्स के तौर पर और https://apis.google.com को दूसरे सोर्स के तौर पर बताया है. ब्राउज़र, apis.google.com से एचटीटीपीएस के साथ-साथ, मौजूदा पेज के ऑरिजिन से JavaScript को सावधानी से डाउनलोड और एक्ज़ीक्यूट करता है.

कंसोल में गड़बड़ी: स्क्रिप्ट 'http://evil.example.com/evil.js' को लोड करने से मना किया गया, क्योंकि यह कॉन्टेंट की सुरक्षा के बारे में नीति का उल्लंघन करता है: script-src 'self' https://apis.google.com

यह नीति तय होने पर, ब्राउज़र किसी दूसरे सोर्स से स्क्रिप्ट लोड करने के बजाय, सिर्फ़ एक गड़बड़ी दिखाता है. जब एक चतुर हमलावर आपकी साइट में कोड डालने में कामयाब होता है, तो वह उम्मीद के मुताबिक सफलता के बजाय गड़बड़ी का मैसेज दिखाएगा.

यह नीति कई तरह के संसाधनों पर लागू होती है

स्क्रिप्ट रिसॉर्स, सुरक्षा के सबसे बड़े जोखिम हैं. हालांकि, सीएसपी में नीति वाले निर्देशों का एक बड़ा सेट होता है. इनसे उन संसाधनों को बेहतर तरीके से कंट्रोल किया जा सकता है जिन्हें पेज को लोड करने की अनुमति है. आपने script-src को पहले ही देख लिया है. इसलिए, कॉन्टेंट का कॉन्सेप्ट समझ में आना चाहिए.

चलिए, संसाधन से जुड़े बाकी डायरेक्टिव के बारे में फटाफट जानते हैं. नीचे दी गई सूची में लेवल 2 के निर्देशों की स्थिति को दिखाया गया है. लेवल 3 की खास जानकारी पब्लिश कर दी गई है, लेकिन इसे मुख्य ब्राउज़र में पूरी तरह से लागू नहीं किया गया है.

  • base-uri उन यूआरएल पर पाबंदी लगाता है जो किसी पेज के <base> एलिमेंट में दिख सकते हैं.
  • child-src, कर्मचारियों और एम्बेड किए गए फ़्रेम के कॉन्टेंट के यूआरएल की सूची बनाता है. उदाहरण के लिए: child-src https://youtube.com से YouTube के वीडियो एम्बेड करने की सुविधा चालू हो जाएगी, लेकिन दूसरे ऑरिजिन के वीडियो एम्बेड नहीं किए जा सकेंगे.
  • connect-src उन ऑरिजिन को सीमित करता है जिनसे कनेक्ट किया जा सकता है (XHR, WebSockets, और EventSource के ज़रिए).
  • font-src उन ऑरिजिन के बारे में बताता है जो वेब फ़ॉन्ट इस्तेमाल कर सकते हैं. Google के वेब फ़ॉन्ट font-src https://themes.googleusercontent.com के ज़रिए चालू किए जा सकते हैं.
  • form-action में <form> टैग से सबमिट किए जाने वाले मान्य एंडपॉइंट की सूची दी गई है.
  • frame-ancestors ऐसे सोर्स के बारे में बताता है जो मौजूदा पेज को एम्बेड कर सकते हैं. यह डायरेक्टिव <frame>, <iframe>, <embed>, और <applet> टैग पर लागू होता है. इस डायरेक्टिव का इस्तेमाल <meta> टैग में नहीं किया जा सकता. यह सिर्फ़ बिना एचटीएमएल वाले रिसॉर्स पर लागू होता है.
  • frame-src को लेवल 2 में बंद कर दिया गया था, लेकिन लेवल 3 में इसे पहले जैसा कर दिया गया है. अगर इसे प्रज़ेंट नहीं किया जाता है, तो वैल्यू अब भी child-src में बदल जाएगी.
  • img-src उन ऑरिजिन के बारे में बताता है जहां से इमेज लोड की जा सकती हैं.
  • media-src उन ऑरिजिन पर पाबंदी लगाता है जिन्हें वीडियो और ऑडियो डिलीवर करने की अनुमति है.
  • object-src, Flash और अन्य प्लगिन को कंट्रोल करने की अनुमति देता है.
  • plugin-types किसी पेज पर लागू होने वाले प्लगिन के टाइप को सीमित करता है.
  • report-uri ऐसे यूआरएल के बारे में बताता है जहां कॉन्टेंट की सुरक्षा से जुड़ी नीति का उल्लंघन होने पर ब्राउज़र, रिपोर्ट भेजेगा. इस डायरेक्टिव का इस्तेमाल <meta> टैग में नहीं किया जा सकता.
  • स्टाइलशीट के लिए, style-src script-src का हिस्सा है.
  • upgrade-insecure-requests उपयोगकर्ता एजेंट को एचटीटीपी को एचटीटीपीएस में बदलकर, यूआरएल स्कीम को फिर से लिखने का निर्देश देता है. यह डायरेक्टिव उन वेबसाइटों के लिए है जिनमें बड़ी संख्या में पुराने यूआरएल हैं और जिन्हें फिर से लिखना होगा.
  • worker-src सीएसपी लेवल 3 का निर्देश है, जो उन यूआरएल पर पाबंदी लगाता है जो वर्कर, शेयर किए गए वर्कर या सर्विस वर्कर के तौर पर लोड हो सकते हैं. जुलाई 2017 से, इस निर्देश को सीमित तौर पर लागू किया गया है.

डिफ़ॉल्ट रूप से, डायरेक्टिव बड़े पैमाने पर खुले होते हैं. अगर किसी डायरेक्टिव के लिए, कोई खास नीति सेट नहीं की जाती है, तो मान लें कि font-src, वह डायरेक्टिव डिफ़ॉल्ट रूप से काम करता है. हालांकि, * को एक मान्य सोर्स के तौर पर इस्तेमाल किया जाता है. उदाहरण के लिए, किसी भी जगह से, बिना किसी पाबंदी के फ़ॉन्ट लोड किए जा सकते हैं.

default-src डायरेक्टिव देकर, यह डिफ़ॉल्ट तरीका बदला जा सकता है. यह डायरेक्टिव, ज़्यादातर उन डायरेक्टिव के लिए डिफ़ॉल्ट सेटिंग के बारे में बताता है जिनके बारे में जानकारी नहीं दी जाती है. आम तौर पर, यह -src पर खत्म होने वाले किसी भी डायरेक्टिव पर लागू होता है. अगर default-src को https://example.com पर सेट किया जाता है और font-src डायरेक्टिव नहीं दिया जाता, तो फ़ॉन्ट https://example.com के बजाय कहीं और लोड किया जा सकता है. हमने अपने शुरुआती उदाहरणों में सिर्फ़ script-src के बारे में बताया था. इसका मतलब है कि इमेज, फ़ॉन्ट वगैरह किसी भी ऑरिजिन से लोड किए जा सकते हैं.

नीचे दिए गए निर्देश, default-src का इस्तेमाल फ़ॉलबैक के तौर पर नहीं करते हैं. याद रखें कि उन्हें सेट न कर पाना, ठीक वैसा ही है जैसा किसी चीज़ को अनुमति देने से होता है.

  • base-uri
  • form-action
  • frame-ancestors
  • plugin-types
  • report-uri
  • sandbox

अपने ऐप्लिकेशन के लिए, जितने चाहें उतने या कम निर्देश इस्तेमाल किए जा सकते हैं. ऐसा करते समय, हर डायरेक्टिव को सेमीकॉलन से अलग करते हुए, बस एचटीटीपी हेडर में उनकी सूची बनाएं. पक्का करें कि आपने एक ही एक डायरेक्टिव में, किसी खास टाइप के सभी ज़रूरी संसाधनों की जानकारी दी हो. अगर आपने script-src https://host1.com; script-src https://host2.com जैसा कुछ लिखा है, तो दूसरे निर्देश को अनदेखा कर दिया जाएगा. जैसा नीचे बताया गया है, उसमें दोनों ऑरिजिन को सही तरीके से मान्य बताया जाएगा:

script-src https://host1.com https://host2.com

उदाहरण के लिए, अगर आपका कोई ऐसा ऐप्लिकेशन है जो कॉन्टेंट डिलीवरी नेटवर्क (जैसे, https://cdn.example.net) से अपने सभी संसाधन लोड करता है और आपको पता है कि आपको किसी फ़्रेम किए गए कॉन्टेंट या प्लगिन की ज़रूरत नहीं है, तो आपकी नीति कुछ इस तरह से दिख सकती है:

Content-Security-Policy: default-src https://cdn.example.net; child-src 'none'; object-src 'none'

क्रियान्वयन विवरण

आपको वेब पर अलग-अलग ट्यूटोरियल में X-WebKit-CSP और X-Content-Security-Policy हेडर दिखेंगे. आगे से, आपको इन प्रीफ़िक्स वाले हेडर को अनदेखा करना होगा. आधुनिक ब्राउज़र (IE को छोड़कर) पर प्रीफ़िक्स नहीं किया गया Content-Security-Policy हेडर काम करता है. आपको इसी हेडर का इस्तेमाल करना चाहिए.

आप चाहे किसी भी हेडर का इस्तेमाल करें, हर पेज के हिसाब से नीति तय होती है: आपको एचटीटीपी हेडर को हर उस जवाब के साथ भेजना होगा जो आपको सुरक्षित रखना है. इससे बहुत ज़्यादा सुविधाएं मिलती हैं, क्योंकि आपके पास किसी पेज की खास ज़रूरतों के हिसाब से उसके लिए नीति को बेहतर बनाने का विकल्प होता है. ऐसा हो सकता है कि आपकी साइट के पेजों के एक सेट में +1 बटन हो, जबकि अन्य में नहीं: बटन कोड को सिर्फ़ ज़रूरत पड़ने पर ही लोड किया जा सकता है.

हर डायरेक्टिव में मौजूद सोर्स सूची में ज़रूरत के हिसाब से बदलाव किए जा सकते हैं. सोर्स को स्कीम (data:, https:) के हिसाब से या सिर्फ़ होस्टनेम से लेकर किसी खास रेंज (example.com, जो उस होस्ट पर किसी भी ऑरिजिन से मैच होता हो: कोई भी स्कीम, कोई भी पोर्ट) से पूरी तरह क्वालिफ़ाइड यूआरआई (https://example.com:443, जो सिर्फ़ एचटीटीपीएस, सिर्फ़ example.com, और सिर्फ़ पोर्ट 443 से मेल खाता है) तक बता सकता है. वाइल्डकार्ड का इस्तेमाल सिर्फ़ स्कीम, पोर्ट या होस्टनेम की बाईं ओर मौजूद जगह पर करके किया जा सकता है: *://*.example.com:*, किसी भी पोर्ट पर किसी भी स्कीम का इस्तेमाल करके, example.com के सभी सबडोमेन से मेल खाएगा नहीं कि example.com.

सोर्स सूची में चार कीवर्ड भी स्वीकार किए जाते हैं:

  • 'none', आपकी उम्मीद के मुताबिक किसी भी चीज़ से मेल नहीं खाता.
  • 'self' मौजूदा ऑरिजिन से मेल खाता है, लेकिन उसके सबडोमेन से नहीं.
  • 'unsafe-inline', इनलाइन JavaScript और सीएसएस को अनुमति देता है. (हम इस पर कुछ देर में और विस्तार से बात करेंगे.)
  • 'unsafe-eval', eval जैसे टेक्स्ट-टू-JavaScript मैकेनिज़्म की अनुमति देता है. (हम भी इस पर बात करेंगे.)

इन कीवर्ड के लिए सिंगल कोट ज़रूरी हैं. उदाहरण के लिए, script-src 'self' (कोटेशन के साथ) मौजूदा होस्ट से JavaScript के इस्तेमाल करने की अनुमति देता है; script-src self (बिना कोट के) "self" नाम के सर्वर से JavaScript को चलाने की अनुमति देता है (न कि मौजूदा होस्ट से ). यह शायद आपकी समझ से मेल न खाता हो.

सैंडबॉक्सिंग

इसके बारे में बात करने लायक एक और डायरेक्टिव है: sandbox. यह उन संसाधनों से थोड़ा अलग है जिन्हें हमने देखा है. क्योंकि यह पेज के लोड हो सकने वाले संसाधनों के बजाय, पेज पर की जा सकने वाली कार्रवाइयों पर प्रतिबंध लगाता है. अगर sandbox डायरेक्टिव मौजूद है, तो पेज को ऐसा माना जाता है जैसे पेज को sandbox एट्रिब्यूट वाले <iframe> के अंदर लोड किया गया हो. इससे पेज पर कई तरह के असर पड़ सकते हैं: पेज को एक यूनीक ऑरिजिन पर ले जाना और फ़ॉर्म सबमिट होने से रोकना वगैरह. यह लेख में दी गई जानकारी से थोड़ी दूर है. हालांकि, आपको HTML5 की खास जानकारी के "सैंडबॉक्सिंग" सेक्शन में, मान्य सैंडबॉक्सिंग एट्रिब्यूट के बारे में पूरी जानकारी मिल सकती है.

मेटा टैग

सीएसपी का पसंदीदा डिलीवरी तरीका एक एचटीटीपी हेडर है. हालांकि, सीधे मार्कअप में किसी पेज पर नीति सेट करना मददगार हो सकता है. ऐसा करने के लिए, http-equiv एट्रिब्यूट वाले <meta> टैग का इस्तेमाल करें:

<meta
  http-equiv="Content-Security-Policy"
  content="default-src https://cdn.example.net; child-src 'none'; object-src 'none'"
/>

इसे frame-ancestors, report-uri या sandbox के लिए इस्तेमाल नहीं किया जा सकता.

इनलाइन कोड को नुकसान पहुंचाने वाला माना जाता है

यह साफ़ तौर पर बताया जाना चाहिए कि सीएसपी को अनुमति वाले ऑरिजिन के हिसाब से बनाया जाता है. इससे ब्राउज़र को यह निर्देश दिया जाता है कि वह संसाधनों के खास सेट को स्वीकार करे और बाकी संसाधनों को अस्वीकार करे. हालांकि, ऑरिजिन के आधार पर अनुमति वाली सूची से, XSS हमलों से पैदा हुए सबसे बड़े खतरे का समाधान नहीं हो पाता है: इनलाइन स्क्रिप्ट इंजेक्शन. अगर कोई हमलावर ऐसा स्क्रिप्ट टैग इंजेक्ट कर सकता है जिसमें सीधे तौर पर कुछ नुकसान पहुंचाने वाला पेलोड (<script>sendMyDataToEvilDotCom();</script>) शामिल हो, तो ब्राउज़र के पास उसे किसी सही इनलाइन स्क्रिप्ट टैग से अलग करने का कोई तरीका नहीं है. सीएसपी इस समस्या को इनलाइन स्क्रिप्ट पर पूरी तरह से बैन करके हल कर देता है: यह पक्का करने का यही एक तरीका है.

इस पाबंदी में, सीधे तौर पर script टैग में एम्बेड की गई स्क्रिप्ट के साथ-साथ इनलाइन इवेंट हैंडलर और javascript: यूआरएल भी शामिल हैं. आपको script टैग के कॉन्टेंट को किसी बाहरी फ़ाइल में ले जाना होगा. साथ ही, javascript: यूआरएल और <a ... onclick="[JAVASCRIPT]"> को सही addEventListener() कॉल से बदलना होगा. उदाहरण के लिए, इन्हें दोबारा लिखा जा सकता है:

<script>
  function doAmazingThings() {
    alert('YOU AM AMAZING!');
  }
</script>
<button onclick="doAmazingThings();">Am I amazing?</button>

इससे मिलता-जुलता है:

<!-- amazing.html -->
<script src="amazing.js"></script>
<button id="amazing">Am I amazing?</button>

<div style="clear:both;"></div>
// amazing.js
function doAmazingThings() {
  alert('YOU AM AMAZING!');
}
document.addEventListener('DOMContentLoaded', function () {
  document.getElementById('amazing').addEventListener('click', doAmazingThings);
});

दोबारा लिखे गए कोड के कई फ़ायदे हैं, जो सीएसपी के साथ अच्छी तरह से काम नहीं करते. यह सबसे सही तरीका है, चाहे आपने सीएसपी का इस्तेमाल किया हो या नहीं. इनलाइन JavaScript, स्ट्रक्चर और व्यवहार को ठीक उसी तरह मिलाता है जैसा आपको नहीं करना चाहिए. बाहरी रिसॉर्स, ब्राउज़र के लिए कैश मेमोरी में सेव करने में आसान होते हैं. डेवलपर इन्हें समझने में आसान होते हैं. साथ ही, ये रिसॉर्स को कंपाइल करने और छोटा करने में मदद करते हैं. कोड को बाहरी रिसॉर्स में ले जाने पर, बेहतर कोड लिखा जा सकता है.

इनलाइन स्टाइल का इस्तेमाल भी इसी तरीके से किया जाता है: style एट्रिब्यूट और style टैग, दोनों को बाहरी स्टाइलशीट में एक साथ मिला दिया जाना चाहिए. ऐसा करके, सीएसएस का इस्तेमाल करके, कई तरह के अद्भुत डेटा बाहर निकाले जाने से बचाया जा सकता है.

अगर आपके पास इनलाइन स्क्रिप्ट और स्टाइल होना ज़रूरी है, तो इसे चालू करने के लिए, script-src या style-src डायरेक्टिव में 'unsafe-inline' को अनुमति वाले सोर्स के तौर पर जोड़ें. नॉन्स या हैश का भी इस्तेमाल किया जा सकता है (नीचे देखें), लेकिन आपको ऐसा नहीं करना चाहिए. इनलाइन स्क्रिप्ट को बंद करना, सीएसपी के लिए सबसे बड़ी सुरक्षा है. साथ ही, इनलाइन स्टाइल पर पाबंदी लगाने से आपका ऐप्लिकेशन सख्त हो जाता है. सभी कोड को दूसरी लाइन में ले जाने के बाद, चीज़ें सही तरीके से काम करें, यह पक्का करने के लिए थोड़ी-बहुत मेहनत करनी पड़ती है. हालांकि, यह एक अहम फ़ायदा है.

अगर आपको इसका इस्तेमाल करना ज़रूरी हो,

सीएसपी लेवल 2 में, इनलाइन स्क्रिप्ट के लिए पुराने सिस्टम के साथ काम करने की सुविधा मिलती है. इसके लिए, आपको क्रिप्टोग्राफ़िक नॉन्स (एक बार इस्तेमाल किया गया नंबर) या हैश का इस्तेमाल करके, अनुमति वाली सूची में खास इनलाइन स्क्रिप्ट जोड़ने की सुविधा मिलती है. हालांकि यह बोझिल हो सकता है, लेकिन यह चुटकी भर काम आ जाता है.

नॉन्स का इस्तेमाल करने के लिए, अपने स्क्रिप्ट टैग को नॉन्स एट्रिब्यूट दें. इसकी वैल्यू, भरोसेमंद सोर्स की सूची में मौजूद किसी एक वैल्यू से मेल खानी चाहिए. उदाहरण के लिए:

<script nonce="EDNnf03nceIOfn39fn3e9h3sdfa">
  // Some inline code I can't remove yet, but need to asap.
</script>

अब, nonce- कीवर्ड में जोड़े गए अपने script-src डायरेक्टिव में नॉन्स जोड़ें.

Content-Security-Policy: script-src 'nonce-EDNnf03nceIOfn39fn3e9h3sdfa'

याद रखें कि पेज के हर अनुरोध के लिए नॉन्स को फिर से जनरेट करना चाहिए और वे समझ में न आने चाहिए.

हैश भी इसी तरह से काम करते हैं. स्क्रिप्ट टैग में कोड जोड़ने के बजाय, स्क्रिप्ट का SHA हैश बनाएं और उसे script-src डायरेक्टिव में जोड़ें. उदाहरण के लिए, मान लें कि आपके पेज में यह शामिल था:

<script>
  alert('Hello, world.');
</script>

आपकी नीति में यह शामिल होगा:

Content-Security-Policy: script-src 'sha256-qznLcsROx4GACP2dm0UCKCzCG-HiZ1guq6ZZDob_Tng='

यहां ध्यान देने के लिए कुछ बातें बताई गई हैं. sha*- प्रीफ़िक्स उस एल्गोरिदम के बारे में बताता है जो हैश जनरेट करता है. ऊपर दिए गए उदाहरण में, sha256- का इस्तेमाल किया गया है. सीएसपी, sha384- और sha512- के साथ भी काम करता है. हैश जनरेट करते समय, <script> टैग शामिल न करें. साथ ही, कैपिटल लेटर और खाली सफ़ेद जगह का भी इस्तेमाल किया जाता है. इसमें आगे या पीछे की खाली सफ़ेद जगह शामिल है.

SHA हैश जनरेट करने से जुड़ी Google की खोज आपको कई भाषाओं में हल कर देगी. Chrome 40 या इसके बाद के वर्शन का इस्तेमाल करके, DevTools खोलकर अपना पेज फिर से लोड किया जा सकता है. कंसोल टैब में, आपकी हर इनलाइन स्क्रिप्ट के लिए सही sha256 हैश के साथ गड़बड़ी के मैसेज होंगे.

मूल्यांकन भी करें

भले ही, हमलावर सीधे स्क्रिप्ट इंजेक्ट न कर पाएं, फिर भी वे आपके ऐप्लिकेशन को चकमा देने वाले टेक्स्ट को एक्ज़ीक्यूटेबल JavaScript में बदल सकते हैं और उसे अपनी ओर से एक्ज़ीक्यूट कर सकते हैं. eval(), new Function(), setTimeout([string], ...), और setInterval([string], ...) सभी वेक्टर होते हैं जिनकी मदद से इंजेक्ट किया गया टेक्स्ट, अनचाहे तरीके से नुकसान पहुंचा सकता है. इस जोखिम को लेकर सीएसपी का डिफ़ॉल्ट जवाब होता है कि वह इन सभी वेक्टर को पूरी तरह से ब्लॉक कर दे.

ऐप्लिकेशन बनाने के आपके तरीके पर, इसका कुछ असर पड़ा है:

  • आपको eval पर भरोसा करने के बजाय, पहले से मौजूद JSON.parse के ज़रिए JSON को पार्स करना होगा. नेटिव JSON ऑपरेशन IE8 के बाद से हर ब्राउज़र में उपलब्ध हैं और ये पूरी तरह से सुरक्षित हैं.
  • जो setTimeout या setInterval फ़िलहाल किए जा रहे हैं उन्हें स्ट्रिंग के बजाय इनलाइन फ़ंक्शन की मदद से फिर से लिखें. उदाहरण के लिए:
setTimeout("document.querySelector('a').style.display = 'none';", 10);

तो बेहतर होगा कि इसे इस तरह लिखा जाए:

setTimeout(function () {
  document.querySelector('a').style.display = 'none';
}, 10);
  • रनटाइम के दौरान इनलाइन टेंप्लेट बनाने से बचें: कई टेंप्लेट लाइब्रेरी, रनटाइम के दौरान टेंप्लेट जनरेट करने की प्रोसेस को तेज़ करने के लिए, new Function() का इस्तेमाल बेहतर तरीके से करती हैं. यह डाइनैमिक प्रोग्रामिंग का एक बेहतरीन ऐप्लिकेशन है. हालांकि, इससे नुकसान पहुंचाने वाले टेक्स्ट की जांच की जा सकती है. कुछ फ़्रेमवर्क, सीएसपी के साथ काम करते हैं. eval न होने पर, वे बेहतर पार्सर बन जाते हैं. AngularJS का ng-csp डायरेक्टिव इसका अच्छा उदाहरण है.

हालांकि, एक बेहतर विकल्प ऐसी प्रोग्रामिंग भाषा होगी जिसमें पहले से कंपाइलेशन करने की सुविधा होती है (उदाहरण के लिए, हैंडलबार यह काम करता है). अपने टेंप्लेट को पहले से कंपाइल करने से उपयोगकर्ता अनुभव, सबसे तेज़ रनटाइम को लागू करने के मुकाबले तेज़ हो सकता है. साथ ही, यह ज़्यादा सुरक्षित भी होता है. अगर eval और इसके टेक्स्ट-टू-JavaScript ब्रेथन आपके ऐप्लिकेशन के लिए ज़रूरी हैं, तो उन्हें script-src डायरेक्टिव में अनुमति वाले सोर्स के तौर पर 'unsafe-eval' जोड़कर चालू किया जा सकता है. हालांकि, हम ऐसा करने का सुझाव नहीं देते. स्ट्रिंग को एक्ज़ीक्यूट करने की सुविधा पर रोक लगाने से, किसी हमलावर के लिए आपकी साइट पर बिना अनुमति वाले कोड को लागू करना बहुत मुश्किल हो जाता है.

रिपोर्ट करना

क्लाइंट-साइड गैर-भरोसेमंद संसाधनों को ब्लॉक करने की सीएसपी की सुविधा आपके उपयोगकर्ताओं के लिए बहुत बड़ी सुविधा है. हालांकि, सर्वर को वापस भेजी जाने वाली सूचना की मदद से, सीएसपी को पहले ही ऐसी गड़बड़ी की पहचान करके उसे ठीक करने में मदद मिलेगी. इसके लिए, ब्राउज़र को report-uri डायरेक्टिव में बताई गई जगह की POST JSON फ़ॉर्मैट में उल्लंघन की रिपोर्ट करने का निर्देश दिया जा सकता है.

Content-Security-Policy: default-src 'self'; ...; report-uri /my_amazing_csp_report_parser;

वे रिपोर्ट कुछ इस तरह दिखेंगी:

{
  "csp-report": {
    "document-uri": "http://example.org/page.html",
    "referrer": "http://evil.example.com/",
    "blocked-uri": "http://evil.example.com/evil.js",
    "violated-directive": "script-src 'self' https://apis.google.com",
    "original-policy": "script-src 'self' https://apis.google.com; report-uri http://example.org/my_amazing_csp_report_parser"
  }
}

इसमें ऐसी जानकारी का एक अच्छा हिस्सा शामिल है, जो उल्लंघन की खास वजह का पता लगाने में आपकी मदद करेगी. इन आंकड़ों में उल्लंघन का पेज (document-uri), उस पेज का रेफ़रर (ध्यान दें कि एचटीटीपी हेडर फ़ील्ड, कुंजी की स्पेलिंग नहीं है), पेज की नीति (blocked-uri), किस निर्देश का उल्लंघन हुआ है (violated-directive), और पेज की पूरी नीति (original-policy) शामिल है.

रिपोर्ट-ओनली

अगर आपने सीएसपी के साथ हाल ही में शुरुआत की है, तो अपने उपयोगकर्ताओं के लिए मुश्किल नीति को लागू करने से पहले, अपने ऐप्लिकेशन की मौजूदा स्थिति का आकलन करें. पूरी तरह से डिप्लॉयमेंट के लिए, ब्राउज़र को नीति पर नज़र रखने, उल्लंघनों की शिकायत करने, लेकिन पाबंदियां लागू न करने के लिए कहा जा सकता है. Content-Security-Policy हेडर भेजने के बजाय, Content-Security-Policy-Report-Only हेडर भेजें.

Content-Security-Policy-Report-Only: default-src 'self'; ...; report-uri /my_amazing_csp_report_parser;

'सिर्फ़ रिपोर्ट करें' मोड में बताई गई नीति से, प्रतिबंधित संसाधनों को ब्लॉक नहीं किया जाएगा. हालांकि, यह आपकी बताई गई जगह पर उल्लंघन की रिपोर्ट भेजेगा. आप एक नीति को लागू करके दूसरी नीति को मॉनिटर करते हुए दोनों हेडर भी भेज सकते हैं. यह अपने ऐप्लिकेशन के सीएसपी में हुए बदलावों के असर का आकलन करने का एक बेहतरीन तरीका है: किसी नई नीति के लिए रिपोर्टिंग की सुविधा चालू करें, उल्लंघन की रिपोर्ट को मॉनिटर करें, और दिखने वाली गड़बड़ियों को ठीक करें. जब आप इसके असर से संतुष्ट हो जाएं, तो नई नीति को लागू करना शुरू करें.

असल दुनिया में उपयोग

CSP 1 का इस्तेमाल Chrome, Safari, और Firefox में किया जा सकता है. हालांकि, यह IE 10 में बहुत सीमित तरीके से काम करता है. caniuse.com पर इसके बारे में ज़्यादा जानकारी देखी जा सकती है. सीएसपी लेवल 2, Chrome पर 40 वर्शन से उपलब्ध है. Twitter और Facebook जैसी बड़ी साइटों ने हेडर का इस्तेमाल किया (Twitter की केस स्टडी काफ़ी अहम है). साथ ही, इसे अपनी साइटों पर डिप्लॉय किया जा सकता है.

अपने ऐप्लिकेशन के लिए नीति बनाने का पहला कदम, उन रिसॉर्स का आकलन करना है जिन्हें वाकई लोड किया जा रहा है. जब आपको लगे कि आपके ऐप्लिकेशन में चीज़ों को एक साथ रखने के लिए आपका हैंडल है, तो उन ज़रूरी शर्तों के हिसाब से नीति सेट अप करें. चलिए, इस्तेमाल के कुछ सामान्य उदाहरणों के बारे में जानते हैं और यह तय करते हैं कि सीएसपी की सुरक्षा के दायरे में, हम उनकी किस तरह मदद कर सकते हैं.

इस्तेमाल का उदाहरण #1: सोशल मीडिया विजेट

  • Google के +1 बटन में https://apis.google.com की स्क्रिप्ट शामिल है और https://plusone.google.com का <iframe> एम्बेड किया गया है. बटन को एम्बेड करने के लिए, आपके पास ऐसी नीति होनी चाहिए जिसमें ये दोनों ऑरिजिन शामिल हों. कम से कम नीति script-src https://apis.google.com; child-src https://plusone.google.com होगी. आपको यह भी पक्का करना होगा कि Google से मिला JavaScript का स्निपेट किसी बाहरी JavaScript फ़ाइल में डाला गया है. अगर आपने frame-src का इस्तेमाल करके, लेवल 2 पर आधारित नीति लागू की थी, तो आपको लेवल 2 की नीति को बदलकर child-src करना होगा. अब सीएसपी लेवल 3 में इसकी ज़रूरत नहीं है.

  • Facebook के पसंद करें बटन को लागू करने के कई विकल्प हैं. हमारा सुझाव है कि आप <iframe> वर्शन का ही इस्तेमाल करें, क्योंकि इसे आपकी साइट के बाकी हिस्सों से सुरक्षित तरीके से सैंडबॉक्स किया जाता है. इसे ठीक से काम करने के लिए, child-src https://facebook.com डायरेक्टिव की ज़रूरत होती है. ध्यान दें कि डिफ़ॉल्ट रूप से, Facebook से जो <iframe> कोड मिलता है वह मिलता-जुलता यूआरएल //facebook.com लोड करता है. उसे साफ़ तौर पर एचटीटीपीएस तय करने के लिए बदलें: https://facebook.com. अगर आपको एचटीटीपी इस्तेमाल करने की ज़रूरत नहीं है, तो इसका इस्तेमाल करने की कोई ज़रूरत नहीं है.

  • Twitter का ट्वीट बटन, स्क्रिप्ट और फ़्रेम के ऐक्सेस पर निर्भर करता है. इन्हें https://platform.twitter.com पर होस्ट किया जाता है. (इसी तरह, Twitter डिफ़ॉल्ट रूप से एक मिलता-जुलता यूआरएल उपलब्ध कराता है. स्थानीय तौर पर कॉपी/पेस्ट करते समय, एचटीटीपीएस के बारे में बताने के लिए कोड में बदलाव करें.) जब तक Twitter से मिलने वाले JavaScript स्निपेट को किसी बाहरी JavaScript फ़ाइल में भेजा जाएगा, तब तक आपको script-src https://platform.twitter.com; child-src https://platform.twitter.com का इस्तेमाल करने की पूरी कोशिश करनी होगी.

  • दूसरे प्लैटफ़ॉर्म की ज़रूरतें भी ऐसी होती हैं और इन्हें भी इसी तरह पूरा किया जा सकता है. हमारा सुझाव है कि आप 'none' का default-src सेट करें और अपने कंसोल को देखकर पता लगाएं कि विजेट काम करने के लिए आपको किन संसाधनों को चालू करने की ज़रूरत है.

एक से ज़्यादा विजेट शामिल करना आसान है: एक ही टाइप के सभी रिसॉर्स को एक निर्देश में मर्ज करना याद रखते हुए, बस नीति के डायरेक्टिव को मिलाएं. अगर आपको तीनों सोशल मीडिया विजेट चाहिए, तो नीति इस तरह दिखेगी:

script-src https://apis.google.com https://platform.twitter.com; child-src https://plusone.google.com https://facebook.com https://platform.twitter.com

इस्तेमाल का उदाहरण #2: लॉकडाउन

कुछ समय के लिए मान लें कि आपकी कोई बैंकिंग साइट है और आपको यह पक्का करना है कि सिर्फ़ वे संसाधन ही लोड हों जिन्हें आपने खुद लिखा है. इस स्थिति में, किसी ऐसी डिफ़ॉल्ट नीति से शुरुआत करें जो पूरी तरह से सभी (default-src 'none') को ब्लॉक करती है और वहां से तैयार करें.

मान लें कि बैंक किसी सीडीएन से https://cdn.mybank.net पर सभी इमेज, स्टाइल, और स्क्रिप्ट लोड करता है और अलग-अलग डेटा को हटाने के लिए, XHR के ज़रिए https://api.mybank.com/ से कनेक्ट होता है. फ़्रेम का इस्तेमाल किया जाता है, लेकिन सिर्फ़ साइट के स्थानीय पेजों के लिए (तीसरे पक्ष का कोई ऑरिजिन नहीं). साइट पर कोई फ़्लैश नहीं है, कोई फ़ॉन्ट नहीं है, न ही कुछ और है. हम सबसे ज़्यादा पाबंदी वाला सीएसपी हेडर भेज सकते हैं:

Content-Security-Policy: default-src 'none'; script-src https://cdn.mybank.net; style-src https://cdn.mybank.net; img-src https://cdn.mybank.net; connect-src https://api.mybank.com; child-src 'self'

इस्तेमाल का उदाहरण #3: सिर्फ़ एसएसएल

शादी की अंगूठी पर चर्चा करने वाले फ़ोरम का एडमिन यह पक्का करना चाहता है कि सभी संसाधन सिर्फ़ सुरक्षित चैनलों के ज़रिए लोड हों, लेकिन वह ज़्यादा कोड नहीं लिखता. तीसरे पक्ष के फ़ोरम सॉफ़्टवेयर के बड़े हिस्सों को इनलाइन स्क्रिप्ट और स्टाइल के साथ पूरी तरह से लिख देना. उसकी काबिलीयत से बाहर है. यह नीति लागू होगी:

Content-Security-Policy: default-src https:; script-src https: 'unsafe-inline'; style-src https: 'unsafe-inline'

भले ही https: की जानकारी default-src में दी गई है, लेकिन स्क्रिप्ट और स्टाइल डायरेक्टिव उस सोर्स को अपने-आप इनहेरिट नहीं करते. हर निर्देश उस खास तरह के संसाधन के डिफ़ॉल्ट को पूरी तरह से ओवरराइट कर देता है.

आने वाला समय

कॉन्टेंट की सुरक्षा के लिए बनी नीति का दूसरा लेवल, उम्मीदवार के लिए सुझाव है. W3C के Web ऐप्लिकेशन Security Working Group ने स्पेसिफ़िकेशन के अगले वर्शन, कॉन्टेंट सिक्योरिटी पॉलिसी लेवल 3 पर काम करना शुरू कर दिया है.

अगर आपको आने वाली इन सुविधाओं पर चर्चा करनी है, तो public-webappsec@ ईमेल पाने वाले लोगों की सूची के संग्रह को देखें या खुद से शामिल हो जाएं.

सुझाव/राय दें या शिकायत करें