क्या मैं किसी ब्राउज़र को तत्व में <script> s नहीं चलाने के लिए कह सकता हूँ?


84

क्या किसी HTML दस्तावेज़ के विशिष्ट भागों से जावास्क्रिप्ट को नहीं चलाना ब्राउज़र को बताना संभव है?

पसंद:

<div script="false"> ...

यह एक अतिरिक्त सुरक्षा सुविधा के रूप में उपयोगी हो सकता है। मेरे द्वारा वांछित सभी स्क्रिप्ट दस्तावेज़ के एक विशिष्ट भाग में लोड की जाती हैं। दस्तावेज़ के अन्य भागों में कोई स्क्रिप्ट नहीं होनी चाहिए और यदि वे हैं तो उन्हें नहीं चलाया जाना चाहिए।


1
यह नही है कि मैं जानता हूँ। यह एक उत्तर के बजाय एक टिप्पणी है, क्योंकि मैं 100% नहीं कह सकता
फ्रीफ़ेक्टर

4
@ chiastic- सुरक्षा आप DOM लोड होने के बाद केवल DOM को पार कर सकते हैं। इस बिंदु पर उस खंड में कोई भी जेएस निष्पादित किया जाएगा।
काउल्स

8
निकटतम मैं सोच सकता हूं कि सामग्री सुरक्षा नीति है, जहां आप स्क्रिप्ट को उनके मूल (शायद यही आप चाहते हैं) द्वारा प्रतिबंधित कर सकते हैं। उदाहरण के लिए, script-src:"self"आप अपने डोमेन से केवल स्क्रिप्ट को पृष्ठ में चलाने की अनुमति देकर निर्दिष्ट करते हैं। यदि आप रुचि रखते हैं, तो सीएसपी के बारे में माइक वेस्ट का यह लेख पढ़ें ।
क्रिस्टोफ

1
@ chiastic- सुरक्षा आप हेडर के भेजे जाने के बाद हेडर में निर्दिष्ट प्रतिबंध को शिथिल करने की योजना कैसे बनाते हैं? वैसे भी, चूंकि CSP डिफ़ॉल्ट रूप से इनलाइन स्क्रिप्ट को निष्क्रिय कर देता है, और रिमोट स्क्रिप्ट को तब तक लोड नहीं किया जाएगा जब तक कि श्वेतसूची में लोड न हो, आपको इसे किसी और चीज़ से संयोजित करने की आवश्यकता क्यों होगी? सीएसपी संभवतः ओपी का सबसे अच्छा दांव है; मुझे आशा है कि कोई व्यक्ति CSP उत्तर छोड़ देगा।
डग नबबिट

6
यदि आप अपने HTML में मनमाने ढंग से ब्लॉक इंजेक्ट करने वाले किसी व्यक्ति के बारे में चिंतित हैं, तो आपका प्रस्तावित समाधान उन्हें </div>इस DOM तत्व को बंद करने के लिए इंजेक्शन लगाने से रोकने के लिए कैसे जा रहा है और फिर एक नई शुरुआत <div>कर रहा है जो स्क्रिप्ट नहीं चल रही है?
डेमियन___बेलिवर

जवाबों:


92

हाँ, आप कर सकते हैं :-) जवाब है: सामग्री सुरक्षा नीति (सीएसपी)।

अधिकांश आधुनिक ब्राउज़र इस ध्वज का समर्थन करते हैं , जो केवल एक विश्वसनीय बाहरी फ़ाइल से जावास्क्रिप्ट कोड को लोड करने और सभी आंतरिक जावास्क्रिप्ट कोड को हटाने के लिए ब्राउज़र को बताता है! केवल नकारात्मक पक्ष यह है, आप अपने पूरे पृष्ठ में (केवल एक के लिए <div>) कोई भी इनलाइन जावास्क्रिप्ट का उपयोग नहीं कर सकते हैं । हालाँकि डायनामिक रूप से एक बाहरी फ़ाइल से div सहित एक अलग सुरक्षा नीति के साथ एक वर्कअराउंड हो सकता है, लेकिन मुझे इस बारे में निश्चित नहीं है।

लेकिन अगर आप सभी जावास्क्रिप्ट को बाहरी जावास्क्रिप्ट फ़ाइलों से लोड करने के लिए अपनी साइट को बदल सकते हैं तो आप इस शीर्षक के साथ पूरी तरह से इनलाइन जावास्क्रिप्ट को अक्षम कर सकते हैं!

यहाँ उदाहरण के साथ एक अच्छा ट्यूटोरियल है: HTML5Rocks ट्यूटोरियल

यदि आप इस HTTP-Header ध्वज को भेजने के लिए सर्वर को कॉन्फ़िगर कर सकते हैं तो दुनिया एक बेहतर जगह होगी!


2
+1 यह वास्तव में अच्छा है, मुझे पता नहीं था कि अस्तित्व में है! (एक ध्यान दें, आपका विकी लिंक सीधे जर्मन संस्करण में है) यहाँ ब्राउज़र समर्थन के बारे में बताया
BrianH

4
ध्यान दें कि यदि आप ऐसा करते हैं, तब भी किसी पृष्ठ पर मौजूद उपयोगकर्ता इनपुट की अनुमति देना अभी भी एक बुरा विचार है। यह मूल रूप से उपयोगकर्ता को पेज को बदलने की अनुमति देगा, हालांकि वे चाहते हैं। यहां तक ​​कि सभी सामग्री सुरक्षा नीति (CSP) सेटिंग्स के साथ अधिकतम करने के लिए सेट (इनलाइन स्क्रिप्ट, शैली आदि को अस्वीकार करना), उपयोगकर्ता अभी भी GET अनुरोधों के लिए छवि srcs का उपयोग करके क्रॉस-साइट अनुरोध जालसाजी (CSRF) हमले कर सकता है, या उपयोगकर्ता को धोखा दे सकता है। POST अनुरोधों के लिए फ़ॉर्म सबमिट बटन पर क्लिक करना।
Ajedi32

@ Ajedi32 निश्चित रूप से आपको उपयोगकर्ता इनपुट को हमेशा साफ करना चाहिए। लेकिन CSP छवियों या सीएसएस जैसे GET अनुरोधों के लिए नीतियां भी निर्धारित कर सकता है, यह न केवल उन्हें ब्लॉक करेगा बल्कि आपके सर्वर को भी इसके बारे में सूचित करेगा!
फाल्को

1
@ फ़ाल्को मैंने डॉक्स पढ़ा , और मेरी समझ यह थी कि आप केवल उन अनुरोधों को किसी दिए गए डोमेन तक सीमित रख सकते हैं, न कि डोमेन पर उप-चरणों का एक विशिष्ट सेट। संभवतः आपके द्वारा सेट किया गया डोमेन आपकी साइट के समान होगा, जिसका अर्थ है कि आप अभी भी CSRF हमलों के लिए खुले रहेंगे।
अजादी ३२

3
@ फाल्को हाँ, कि मूल रूप से StackExchange ने नए Stack Snippets फ़ीचर के साथ क्या किया है: blog.stackoverflow.com/2014/09/… यदि आप इनपुट को ठीक से साफ कर लेते हैं , तो एक अलग डोमेन आवश्यक नहीं है।
Ajedi32

13

आप घटना <script>का उपयोग करके जावास्क्रिप्ट को लोड कर सकते हैं beforescriptexecute:

<script>
  // Run this as early as possible, it isn't retroactive
  window.addEventListener('beforescriptexecute', function(e) {
    var el = e.target;
    while(el = el.parentElement)
      if(el.hasAttribute('data-no-js'))
        return e.preventDefault(); // Block script
  }, true);
</script>

<script>console.log('Allowed. Console is expected to show this');</script>
<div data-no-js>
  <script>console.log('Blocked. Console is expected to NOT show this');</script>
</div>

ध्यान दें कि beforescriptexecuteHTML 5.0 में परिभाषित किया गया था लेकिन HTML 5.1 में हटा दिया गया है। फ़ायरफ़ॉक्स एकमात्र प्रमुख ब्राउज़र है जिसने इसे लागू किया है।

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

और यह चीजों को ब्लॉक नहीं करेगा <img onerror="javascript:alert('foo')" src="//" />


फिडल अपेक्षा के अनुरूप काम नहीं करता है। मुझे "अवरुद्ध" भाग को देखने में सक्षम नहीं होना चाहिए, है ना?
सलमान ए

@ सलमान सटीक। संभवतः, आपका ब्राउज़र beforescriptexecuteईवेंट का समर्थन नहीं करता है । यह फ़ायरफ़ॉक्स पर काम करता है।
ओडोल

शायद क्योंकि यह क्रोम में काम नहीं कर रहा है, स्निपेट के साथ, जैसा कि प्रदान किया गया है, हालांकि मैं देखता हूं कि आपने इसे केवल एक स्निपेट में बदल दिया है :-)
मार्क हर्ड

beforescriptexecuteऐसा लगता है कि यह समर्थित नहीं है और अधिकांश प्रमुख ब्राउज़रों द्वारा समर्थित नहीं होगा। developer.mozilla.org/en-US/docs/Web/Events/beforescriptexecute
मैट पेनिंगटन

8

दिलचस्प सवाल है, मुझे नहीं लगता कि यह संभव है। लेकिन अगर ऐसा है, तो भी ऐसा लगता है कि यह एक हैक होगा।

यदि उस div की सामग्री अविश्वसनीय है, तो आपको HTTP प्रतिक्रिया में भेजे जाने और ब्राउज़र में रेंडर करने से पहले सर्वर साइड पर डेटा से बचने की आवश्यकता है।

यदि आप केवल <script>टैग हटाना चाहते हैं और अन्य HTML टैग्स की अनुमति देते हैं, तो उन्हें सामग्री से हटा दें और बाकी को छोड़ दें।

XSS की रोकथाम में देखें।

https://www.owasp.org/index.php/XSS_%28Cross_Site_Scripting%29_Prevention_Cheat_Sheet


7

जावास्क्रिप्ट को "इनलाइन" निष्पादित किया जाता है, अर्थात यह उस क्रम में जिसमें यह DOM में दिखाई देता है (यदि ऐसा नहीं था, तो आप कभी भी सुनिश्चित नहीं हो सकते कि किसी भिन्न स्क्रिप्ट में परिभाषित कुछ चर तब दिखाई देता है जब आपने पहली बार इसका उपयोग किया था। )।

तो इसका मतलब है कि सिद्धांत में आपके पास पृष्ठ की शुरुआत में एक स्क्रिप्ट हो सकती है (अर्थात पहला <script>तत्व) जो डोम के माध्यम से दिखता है <script>और आपके अंदर के सभी तत्वों और घटना संचालकों को हटा देता है <div>

लेकिन वास्तविकता अधिक जटिल है: डोम और स्क्रिप्ट लोडिंग एसिंक्रोनस रूप से होती है। इसका मतलब है कि ब्राउज़र केवल यह गारंटी देता है कि कोई स्क्रिप्ट DOM के उस हिस्से को देख सकती है जो उसके पहले है (यानी हमारे उदाहरण में अब तक का हैडर)। परे कुछ के लिए कोई गारंटी नहीं है (यह संबंधित है document.write())। तो आप अगला स्क्रिप्ट टैग देख सकते हैं या शायद, आप नहीं।

आप onloadदस्तावेज़ की घटना पर रोक लगा सकते हैं - जो यह सुनिश्चित करेगा कि आपको संपूर्ण DOM मिला है - लेकिन उस समय, दुर्भावनापूर्ण कोड पहले ही निष्पादित किया जा सकता था। चीजें तब और खराब हो जाती हैं जब अन्य स्क्रिप्ट डोम में हेरफेर करते हैं, वहां स्क्रिप्ट जोड़ते हैं। इसलिए आपको DOM के हर बदलाव की जांच करनी होगी।

तो @ USCls समाधान (सर्वर पर फ़िल्टर करना) एकमात्र समाधान है जिसे सभी स्थितियों में काम करने के लिए बनाया जा सकता है।


1

यदि आप अपने ब्राउज़र में जावास्क्रिप्ट कोड प्रदर्शित करना चाहते हैं:

जावास्क्रिप्ट और HTML का उपयोग करते हुए, आपको जावास्क्रिप्ट कोड प्रदर्शित करने और इस कोड को निष्पादित करने से बचने के लिए HTML संस्थाओं का उपयोग करना होगा। यहां आप HTML संस्थाओं की सूची पा सकते हैं:

यदि आप सर्वर-साइड स्क्रिप्टिंग भाषा (PHP, ASP.NET, आदि) का उपयोग कर रहे हैं, तो संभवतः, एक ऐसा कार्य है जो एक स्ट्रिंग से बच जाएगा और विशेष पात्रों को HTML संस्थाओं में परिवर्तित कर देगा। PHP में, आप "htmlspecialchars ()" या "htmlentities ()" का उपयोग करेंगे। बाद के सभी HTML वर्ण शामिल हैं।

यदि आप अपने जावास्क्रिप्ट कोड को अच्छे तरीके से प्रदर्शित करना चाहते हैं, तो कोड हाइलाइटर्स में से एक का प्रयास करें:


1

मुझे एक सिद्धांत मिला है:

  • एक noscriptटैग के अंदर दस्तावेज़ के विशिष्ट भाग को लपेटें ।
  • scriptटैग के अंदर सभी टैग को छोड़ने के लिए DOM फ़ंक्शंस का उपयोग करें और noscriptफिर उसकी सामग्री को खोल दें।

अवधारणा उदाहरण के सबूत:

window.onload = function() {
    var noscripts = /* _live_ list */ document.getElementsByTagName("noscript"),
        memorydiv = document.createElement("div"),
        scripts = /* _live_ list */ memorydiv.getElementsByTagName("script"),
        i,
        j;
    for (i = noscripts.length - 1; i >= 0; --i) {
        memorydiv.innerHTML = noscripts[i].textContent || noscripts[i].innerText;
        for (j = scripts.length - 1; j >= 0; --j) {
            memorydiv.removeChild(scripts[j]);
        }
        while (memorydiv.firstChild) {
            noscripts[i].parentNode.insertBefore(memorydiv.firstChild, noscripts[i]);
        }
        noscripts[i].parentNode.removeChild(noscripts[i]);
    }
};
body { font: medium/1.5 monospace; }
p, h1 { margin: 0; }
<h1>Sample Content</h1>
<p>1. This paragraph is embedded in HTML</p>
<script>document.write('<p style="color: red;">2. This paragraph is generated by JavaScript</p>');</script>
<p>3. This paragraph is embedded in HTML</p>
<h1>Sample Content in No-JavaScript Zone</h1>
<noscript>
    <p>1. This paragraph is embedded in HTML</p>
    <script>document.write('<p style="color: red;">2. This paragraph is generated by JavaScript</p>');</script>
    <p>3. This paragraph is embedded in HTML</p>
</noscript>
<noscript>
    <p>1. This paragraph is embedded in HTML</p>
    <script>document.write('<p style="color: red;">2. This paragraph is generated by JavaScript</p>');</script>
    <p>3. This paragraph is embedded in HTML</p>
</noscript>


यदि div में सामग्री अविश्वास है, जो मुझे लगता है कि यह प्रश्न दिया गया है। वे <noscript>टैग को बंद कर सकते हैं और फिर उन्हें जो पसंद है उसे इंजेक्ट कर सकते हैं।
काउल्स

हां, सर्वर साइड पर समस्या को ठीक करने के लिए उचित समाधान है। मैं जावास्क्रिप्ट के माध्यम से जो कुछ भी कर रहा हूं वह सर्वर की तरफ बेहतर होना चाहिए।
सलमान ए

0

यदि आप बाद में स्क्रिप्ट टैग को फिर से सक्षम करना चाहते हैं, तो मेरा समाधान ब्राउज़र वातावरण को तोड़ना था, ताकि कोई भी स्क्रिप्ट जो एक रन बनाता है वह काफी जल्दी त्रुटि को फेंक देगा। हालाँकि, यह पूरी तरह से विश्वसनीय नहीं है, इसलिए आप इसे सुरक्षा सुविधा के रूप में उपयोग नहीं कर सकते।

यदि आप वैश्विक गुणों को एक्सेस करने का प्रयास करते हैं तो Chrome अपवाद छोड़ देगा।

setTimeout("Math.random()")
// => VM116:25 Uncaught Error: JavaScript Execution Inhibited  

मैं सभी अधिलेखित गुणों को अधिलेखित कर रहा हूं window, लेकिन आप अन्य कार्यक्षमता को तोड़ने के लिए इसका विस्तार भी कर सकते हैं।

window.allowJSExecution = inhibitJavaScriptExecution();
function inhibitJavaScriptExecution(){

    var windowProperties = {};
    var Object = window.Object
    var console = window.console
    var Error = window.Error

    function getPropertyDescriptor(object, propertyName){
        var descriptor = Object.getOwnPropertyDescriptor(object, propertyName);
        if (!descriptor) {
            return getPropertyDescriptor(Object.getPrototypeOf(object), propertyName);
        }
        return descriptor;
    }

    for (var propName in window){
        try {
            windowProperties[propName] = getPropertyDescriptor(window, propName)
            Object.defineProperty(window, propName, {
                get: function(){
                    throw Error("JavaScript Execution Inhibited")
                },
                set: function(){
                    throw Error("JavaScript Execution Inhibited")
                },
                configurable: true
            })
        } catch (err) {}
    }

    return function allowJSExecution(){
        for (var propName in window){
            if (!(propName in windowProperties)) {
                delete windowProperties[propName]
            }
        }

        for (var propName in windowProperties){
            try {
                Object.defineProperty(window, propName, windowProperties[propName])
            } catch (err) {}
        }
    }
}
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.