Czy można powiedzieć przeglądarkom, aby nie uruchamiały JavaScript z określonych części dokumentu HTML?
Lubić:
<div script="false"> ...
Może być przydatna jako dodatkowa funkcja bezpieczeństwa. Wszystkie skrypty, które chcę, są ładowane w określonej części dokumentu. W innych częściach dokumentu nie powinno być skryptów, a jeśli są, nie należy ich uruchamiać.
javascript
html
script-tag
Seppo Erviälä
źródło
źródło
script-src:"self"
że zezwalasz na uruchamianie na stronie tylko skryptów z Twojej domeny. Jeśli jesteś zainteresowany, przeczytaj artykuł Mike'a Westa o CSP .</div>
elementu DOM w celu zamknięcia tego elementu DOM, a następnie rozpoczęcie nowego,<div>
który będzie rodzeństwem tego, w którym nie działają skrypty?Odpowiedzi:
TAK, możesz :-) Odpowiedź brzmi: Polityka bezpieczeństwa treści (CSP).
Większość nowoczesnych przeglądarek obsługuje tę flagę , która mówi przeglądarce tylko, aby ładowała kod JavaScript z zaufanego pliku zewnętrznego i nie zezwalała na cały wewnętrzny kod JavaScript! Jedynym minusem jest to, że nie możesz używać żadnego wbudowanego kodu JavaScript na całej stronie (nie tylko na pojedynczej stronie
<div>
). Chociaż można by obejść ten problem, dynamicznie dołączając element div z pliku zewnętrznego z inną polityką bezpieczeństwa, ale nie jestem tego pewien.Ale jeśli możesz zmienić swoją witrynę, aby ładowała wszystkie skrypty JavaScript z zewnętrznych plików JavaScript, możesz całkowicie wyłączyć wbudowany JavaScript za pomocą tego nagłówka!
Oto fajny samouczek z przykładem: Samouczek HTML5Rocks
Jeśli możesz skonfigurować serwer, aby wysyłał tę flagę nagłówka HTTP, świat będzie lepszym miejscem!
źródło
Możesz zablokować ładowanie JavaScript
<script>
, używającbeforescriptexecute
zdarzenia:<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>
Zauważ, że
beforescriptexecute
zostało to zdefiniowane w HTML 5.0, ale zostało usunięte w HTML 5.1. Firefox jest jedyną dużą przeglądarką, która go wdrożyła.Jeśli umieszczasz na swojej stronie niezaufaną wiązkę kodu HTML, pamiętaj, że blokowanie skryptów wewnątrz tego elementu nie zapewni większego bezpieczeństwa, ponieważ niezaufany kod HTML może zamknąć element w piaskownicy, a zatem skrypt zostanie umieszczony na zewnątrz i uruchomiony.
I to nie blokuje takich rzeczy
<img onerror="javascript:alert('foo')" src="//" />
.źródło
beforescriptexecute
wydarzenia. Działa w przeglądarce Firefox.beforescriptexecute
wygląda na to, że nie jest obsługiwany i nie będzie obsługiwany przez większość głównych przeglądarek. developer.mozilla.org/en-US/docs/Web/Events/beforescriptexecuteCiekawe pytanie, nie sądzę, żeby to było możliwe. Ale nawet jeśli tak jest, wygląda na to, że byłby to hack.
Jeśli zawartość tego elementu div jest niezaufana, musisz uciec przed danymi po stronie serwera, zanim zostaną wysłane w odpowiedzi HTTP i renderowane w przeglądarce.
Jeśli chcesz tylko usunąć
<script>
tagi i zezwolić na inne tagi HTML, po prostu usuń je z treści i zostaw resztę.Zapoznaj się z zapobieganiem XSS.
https://www.owasp.org/index.php/XSS_%28Cross_Site_Scripting%29_Prevention_Cheat_Sheet
źródło
JavaScript jest wykonywany „inline”, tj. W kolejności, w jakiej pojawia się w DOM (gdyby tak nie było, nigdy nie można było być pewnym, że jakaś zmienna zdefiniowana w innym skrypcie była widoczna, gdy używałeś go po raz pierwszy ).
Oznacza to, że teoretycznie możesz mieć skrypt na początku strony (tj. Pierwszy
<script>
element), który przegląda DOM i usuwa wszystkie<script>
elementy i programy obsługi zdarzeń z twojego<div>
.Ale rzeczywistość jest bardziej złożona: ładowanie DOM i skryptu odbywa się asynchronicznie. Oznacza to, że przeglądarka gwarantuje, że skrypt może zobaczyć tylko część DOM, która jest przed nim (tj. Dotychczasowy nagłówek w naszym przykładzie). Nie ma żadnych gwarancji poza (jest to związane
document.write()
). Więc możesz zobaczyć następny tag skryptu, a może nie.Możesz dołączyć do
onload
zdarzenia dokumentu - co zapewniłoby, że masz cały DOM - ale w tym czasie złośliwy kod mógł już zostać wykonany. Sytuacja pogarsza się, gdy inne skrypty manipulują DOM, dodając tam skrypty. Więc musiałbyś też sprawdzać każdą zmianę DOM.Tak więc rozwiązanie @cowls (filtrowanie na serwerze) jest jedynym rozwiązaniem, które może działać w każdej sytuacji.
źródło
Jeśli chcesz wyświetlić kod JavaScript w swojej przeglądarce:
Używając JavaScript i HTML, będziesz musiał używać encji HTML do wyświetlania kodu JavaScript i unikania wykonywania tego kodu. Tutaj możesz znaleźć listę encji HTML:
Jeśli używasz języka skryptowego po stronie serwera (PHP, ASP.NET itp.), Najprawdopodobniej istnieje funkcja, która zmieniłaby ciąg znaków i przekształciłaby znaki specjalne w encje HTML. W PHP należy użyć „htmlspecialchars ()” lub „htmlentities ()”. Ta ostatnia obejmuje wszystkie znaki HTML.
Jeśli chcesz ładnie wyświetlić kod JavaScript, wypróbuj jeden z podświetlaczy kodu:
źródło
Mam teorię:
noscript
znacznik.script
tagi wewnątrznoscript
tagu, a następnie rozpakuj jego zawartość.Przykład dowodu koncepcji:
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>
źródło
<noscript>
tag, a następnie wstrzyknąć to, co chcą.Jeśli chcesz później ponownie włączyć tagi skryptów, moim rozwiązaniem było złamanie środowiska przeglądarki, aby każdy uruchomiony skrypt dość wcześnie zgłaszał błąd. Jednak nie jest to całkowicie niezawodne, więc nie można go używać jako funkcji bezpieczeństwa.
Jeśli spróbujesz uzyskać dostęp do właściwości globalnych, Chrome zgłosi wyjątek.
setTimeout("Math.random()") // => VM116:25 Uncaught Error: JavaScript Execution Inhibited
Nadpisuję wszystkie właściwości
window
, które można nadpisać , ale możesz też rozszerzyć je, aby zepsuć inne funkcje.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) {} } } }
źródło