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