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

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

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

इस खास जानकारी में, एक ऐसी सुरक्षा के बारे में बताया गया है जिससे आधुनिक ब्राउज़र में 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> टैग में नहीं किया जा सकता. यह सिर्फ़ ऐसे संसाधनों पर लागू होता है जो HTML के नहीं होते.
  • frame-src को दूसरे लेवल में बंद कर दिया गया था, लेकिन तीसरे लेवल में इसे वापस लाया गया है. अगर यह विकल्प मौजूद नहीं है, तो यह पहले की तरह child-src पर सेट हो जाएगा.
  • img-src से उन ऑरिजिन के बारे में पता चलता है जिनसे इमेज लोड की जा सकती हैं.
  • media-src, उन ऑरिजिन पर पाबंदी लगाता है जिन्हें वीडियो और ऑडियो डिलीवर करने की अनुमति है.
  • object-src की मदद से, फ़्लैश और अन्य प्लग इन को कंट्रोल किया जा सकता है.
  • 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> में लोड किया गया हो. इससे पेज पर कई तरह के असर पड़ सकते हैं: पेज को यूनीक ऑरिजिन में भेजना और फ़ॉर्म सबमिट करने से रोकना वगैरह. यह इस लेख के दायरे से थोड़ा बाहर है. हालांकि, एचटीएमएल5 स्पेसिफ़िकेशन के "सैंडबॉक्सिंग" सेक्शन में, सैंडबॉक्सिंग के मान्य एट्रिब्यूट के बारे में पूरी जानकारी मिल सकती है.

मेटा टैग

सीएसपी के लिए, डिलीवरी का पसंदीदा तरीका एचटीटीपी हेडर है. हालांकि, सीधे मार्कअप में किसी पेज पर नीति सेट करना फ़ायदेमंद हो सकता है. इसके लिए, 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 के लिए नहीं किया जा सकता.

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

यह साफ़ तौर पर पता चलना चाहिए कि सीएसपी, अनुमति वाली सूची के ऑरिजिन पर आधारित है. ऐसा इसलिए है, क्योंकि यह ब्राउज़र को रिसॉर्स के खास सेट को स्वीकार करने और बाकी को अस्वीकार करने का निर्देश देने का एक साफ़ तरीका है. हालांकि, ऑरिजिन के आधार पर अनुमति वाली सूचियां, एक्सएसएस हमलों से जुड़े सबसे बड़े खतरे को हल नहीं करतीं: इनलाइन स्क्रिप्ट इंजेक्शन. अगर कोई हमलावर ऐसा स्क्रिप्ट टैग इंजेक्ट करता है जिसमें सीधे तौर पर कोई नुकसान पहुंचाने वाला पेलोड (<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> टैग शामिल न करें. कैपिटलाइज़ेशन और स्पेस भी मायने रखते हैं. इनमें शुरुआत या आखिर में मौजूद स्पेस भी शामिल हैं.

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

Eval too

भले ही, हमलावर सीधे तौर पर स्क्रिप्ट इंजेक्ट न कर पाए, लेकिन वह आपके ऐप्लिकेशन को गुमराह करके, काम न करने वाले टेक्स्ट को 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() का ज़्यादा इस्तेमाल करती हैं. यह डायनैमिक प्रोग्रामिंग का एक बेहतरीन ऐप्लिकेशन है. हालांकि, इसमें नुकसान पहुंचाने वाले टेक्स्ट का आकलन करने का जोखिम होता है. कुछ फ़्रेमवर्क, CSP के साथ काम करते हैं.eval के न होने पर, ये किसी बेहतर पार्स करने वाले टूल का इस्तेमाल करते हैं. AngularJS का ng-csp डायरेक्टिव, इसका एक अच्छा उदाहरण है.

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

रिपोर्टिंग

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

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 पर जाकर, ज़्यादा जानकारी देखी जा सकती है. Chrome में सीएसपी लेवल 2, वर्शन 40 से उपलब्ध है. Twitter और Facebook जैसी बड़ी साइटों ने हेडर को डिप्लॉय कर दिया है (Twitter की केस स्टडी पढ़ना ज़रूरी है). साथ ही, यह स्टैंडर्ड आपकी साइटों पर डिप्लॉय करने के लिए पूरी तरह से तैयार है.

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

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

  • 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 का इस्तेमाल करके बनाई गई लेवल 1 की नीति थी, तो लेवल 2 के लिए आपको इसे child-src में बदलना होगा. सीएसपी लेवल 3 में, अब इसकी ज़रूरत नहीं है.

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

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

  • अन्य प्लैटफ़ॉर्म पर भी ऐसी ही ज़रूरी शर्तें होती हैं और उन्हें भी इसी तरह ठीक किया जा सकता है. हमारा सुझाव है कि आप '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

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

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

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

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'

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

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

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

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

आने वाला समय

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

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

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