HTMLドキュメントの特定の部分からJavaScriptを実行しないようにブラウザに指示することは可能ですか?
のような:
<div script="false"> ...
追加のセキュリティ機能として役立ちます。必要なすべてのスクリプトは、ドキュメントの特定の部分に読み込まれます。ドキュメントの他の部分にスクリプトが存在しないようにし、存在する場合は実行しないでください。
はい、できます:-)答えは:コンテンツセキュリティポリシー(CSP)。
最新のブラウザはこのフラグをサポートしています 。これは、信頼できる外部ファイルからJavaScriptコードをロードするだけで、すべての内部JavaScriptコードを許可しないようブラウザに指示します!唯一の欠点は、ページ全体でインラインJavaScriptを使用できないことです(単一の<div>
)。別のセキュリティポリシーを持つ外部ファイルからdivを動的に含めることで回避策がありますが、それについてはわかりません。
ただし、外部JavaScriptファイルからすべてのJavaScriptをロードするようにサイトを変更できる場合、このヘッダーでインラインJavaScriptを完全に無効にできます!
以下に例を示した素晴らしいチュートリアルを示します。 HTML5Rocks Tutorial
このHTTPヘッダーフラグを送信するようにサーバーを構成できる場合、世界はより良い場所になります!
beforescriptexecute
イベントを使用して、_<script>
_によってロードされたJavaScriptをブロックできます。
_<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>
_
beforescriptexecute
はHTML 5.0では定義されていましたが、HTML 5.1では削除されていることに注意してください。 Firefoxは、Firefoxを実装した唯一の主要なブラウザです。
信頼できないHTMLをページに挿入する場合、その要素内のブロックスクリプトはセキュリティを強化しないことに注意してください。信頼できないHTMLはサンドボックス化された要素を閉じることができるため、スクリプトは外部に配置されて実行されます。
そして、これは<img onerror="javascript:alert('foo')" src="//" />
のようなものをブロックしません。
興味深い質問ですが、それは可能だとは思いません。しかし、たとえそうであっても、ハックのように聞こえます。
そのdivのコンテンツが信頼できない場合、HTTP応答で送信され、ブラウザでレンダリングされる前に、サーバー側でデータをエスケープする必要があります。
<script>
タグのみを削除し、他のhtmlタグを許可する場合は、コンテンツからそれらを削除して残りを残します。
XSS防止を調べてください。
https://www.owasp.org/index.php/XSS_%28Cross_Site_Scripting%29_Prevention_Cheat_Sheet
JavaScriptは「インライン」で実行されます。つまり、DOMに表示される順序で実行されます(そうでない場合は、初めて使用したときに別のスクリプトで定義された変数が表示されるとは限りません。 )。
つまり、理論的には、DOMを調べ、<script>
内の<script>
要素とイベントハンドラーをすべて削除するスクリプトをページの先頭(つまり、最初の<div>
要素)に持つことができるということです。
しかし、現実はもっと複雑です。DOMとスクリプトの読み込みは非同期に行われます。これは、ブラウザーがスクリプトがbefore it(つまり、これまでの例ではヘッダー)であるDOMの一部のみを表示できることを保証することを意味します。それ以上の保証はありません(これはdocument.write()
に関連しています)。したがって、次のスクリプトタグが表示される場合もあれば、表示されない場合もあります。
ドキュメントのonload
イベントにラッチできます-これにより、DOM全体を取得できますが、その時点で、悪意のあるコードが既に実行されている可能性があります。他のスクリプトがDOMを操作し、そこにスクリプトを追加すると事態は悪化します。そのため、DOMのすべての変更も確認する必要があります。
したがって、@ cowlsソリューション(サーバーでのフィルタリング)は、すべての状況で機能する唯一のソリューションです。
私は理論を持っています:
noscript
タグで囲みます。script
タグ内のすべての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>
ブラウザにJavaScriptコードを表示する場合:
JavaScriptとHTMLを使用する場合、 HTMLエンティティ を使用してJavaScriptコードを表示し、このコードの実行を回避する必要があります。ここで、HTMLエンティティのリストを見つけることができます。
サーバー側のスクリプト言語(PHP、ASP.NETなど)を使用している場合、おそらく文字列をエスケープし、特殊文字をHTMLエンティティに変換する関数があります。 PHPでは、「htmlspecialchars()」または「htmlentities()」を使用します。後者はすべてのHTML文字をカバーしています。
JavaScriptコードを適切な方法で表示する場合は、コードハイライターのいずれかを試してください。
後でスクリプトタグを再度有効にする場合、私の解決策は、実行中のスクリプトがかなり早くエラーをスローするようにブラウザー環境を壊すことでした。ただし、完全に信頼できるわけではないため、セキュリティ機能として使用することはできません。
グローバルプロパティにアクセスしようとすると、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) {}
}
}
}