वेब का सुरक्षा मॉडल,
एक ही ऑरिजिन से जुड़ी नीति में रूट किया गया है. 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 को सही तरीके से डाउनलोड और एक्ज़ीक्यूट करता है. साथ ही, यह मौजूदा पेज के ऑरिजिन से भी 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>
टैग में इस्तेमाल नहीं किया जा सकता. साथ ही, यह सिर्फ़ बिना एचटीएमएल वाले रिसॉर्स पर लागू होता है.frame-src
को लेवल 2 में रोक दिया गया था. हालांकि, अब इसे तीसरे लेवल में वापस लाया गया है. अगर यह प्रज़ेंट नहीं होता है, तो भी यह पहले की तरह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'
, टेक्स्ट को JavaScript की मदद से प्रोसेस करने की अनुमति देता है, जैसे किeval
. (हम इस बारे में भी बात करेंगे.)
इन कीवर्ड के लिए सिंगल कोट की ज़रूरत होती है. उदाहरण के लिए, 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 Search से आपको कितनी भी भाषाओं में समाधान मिल जाएंगे. Chrome 40 या इसके बाद के वर्शन का इस्तेमाल करके, DevTools खोला जा सकता है. इसके बाद, अपने पेज को फिर से लोड किया जा सकता है. कंसोल टैब में आपकी हर इनलाइन स्क्रिप्ट के लिए, सही sha256 हैश के साथ गड़बड़ी के मैसेज होंगे.
भी आकलन करें
यहां तक कि जब कोई हमलावर सीधे स्क्रिप्ट इंजेक्ट नहीं कर पाता, तब भी वह आपके ऐप्लिकेशन को धोखा देकर,
किसी और तरीके से इस्तेमाल न किए जाने वाले टेक्स्ट को एक्ज़ीक्यूटेबल JavaScript में बदल सकता है और उसकी तरफ़ से उसे एक्ज़ीक्यूट कर सकता है. eval()
, नए
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
डायरेक्टिव में बताई गई जगह की जानकारी, JSON फ़ॉर्मैट वाली उल्लंघन रिपोर्ट POST
करने का निर्देश दिया जा सकता है.
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;
सिर्फ़ रिपोर्ट वाले मोड में बताई गई नीति, प्रतिबंधित संसाधनों को ब्लॉक नहीं करेगी. हालांकि, वह आपकी बताई गई जगह पर उल्लंघन की रिपोर्ट भेजेगी. इतना ही नहीं, दोनों हेडर भी भेजे जा सकते हैं. ऐसा करके, दूसरी नीति को मॉनिटर करते हुए एक नीति लागू की जा सकती है. यह अपने ऐप्लिकेशन के सीएसपी में हुए बदलावों के असर का आकलन करने का एक बेहतरीन तरीका है: नई नीति के लिए रिपोर्ट करने की सुविधा चालू करना, उल्लंघन की रिपोर्ट पर नज़र रखना और गड़बड़ी होने पर उसे ठीक करना. जब आप इसके असर से संतुष्ट हों, तो नई नीति लागू करना शुरू करें.
रीयल वर्ल्ड का इस्तेमाल
Chrome, Safari, और Firefox में CSP 1 का काफ़ी इस्तेमाल किया जा सकता है, लेकिन IE 10 में यह बहुत सीमित है. caniuse.com पर जाकर खास जानकारी देखें. सीएसपी लेवल 2, Chrome में वर्शन 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
लेवल 2 का इस्तेमाल करने वाली, लेवल 1 पर आधारित नीति थी, तो आपको इसे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/
से कनेक्ट करता है. फ़्रेम का इस्तेमाल किया जाता है, लेकिन सिर्फ़ साइट के स्थानीय पेजों के लिए (तीसरे पक्ष से कोई ऑरिजिन नहीं). साइट पर कोई Flash, कोई फ़ॉन्ट, कोई अतिरिक्त
नहीं है. हम जो सबसे ज़्यादा सीमित सीएसपी हेडर भेज सकते हैं, वह यह है:
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'
default-src
में https:
के बारे में बताया गया है, लेकिन स्क्रिप्ट और स्टाइल डायरेक्टिव अपने-आप उस सोर्स को इनहेरिट नहीं करते. हर डायरेक्टिव, उस खास तरह के संसाधन के लिए डिफ़ॉल्ट को पूरी तरह से ओवरराइट कर देता है.
आने वाला समय
कॉन्टेंट की सुरक्षा नीति का दूसरा लेवल, उम्मीदवार के लिए सुझाव है. W3C के वेब ऐप्लिकेशन सिक्योरिटी वर्किंग ग्रुप ने स्पेसिफ़िकेशन में किए जाने वाले अगले बदलाव, कॉन्टेंट की सुरक्षा नीति लेवल 3 पर पहले ही काम करना शुरू कर दिया है.
अगर आपको आने वाली इन सुविधाओं की चर्चा करनी है, तो पब्लिक-webappsec@ ईमेल पाने वाले लोगों की सूची के संग्रह को हाइलाइट करें या खुद से इसमें शामिल हों.