8

私はたまたまXSSとそれを回避する方法について読みました。私が読んだことから、Webアプリケーションをある程度XSSで安全にするには、入力フィルタリング、アプリケーションコードの適切な処理、および出力エンコーディングが必要であることがわかりました。いくつかの記事を読んだ後でも、いくつかの疑問が残っています。

  • jQuery.text( "untrusted_data")またはelement.text = untrusted_dataを試したところ、ブラウザはコンテンツを完全にエンコードしているようですが、クライアント側のエンコードは信頼されるべきではなく、「常に」サーバー側でエンコードします。クライアント側のエンコーディングが安全でないと見なされるのはなぜですか?

  • jQuery.val(untrusted_data)またはelement.value = untrusted_dataを使用して値を設定しようとしたときはいつでも、十分に安全であるように思われます。それで、それは本当にXSS安全ですか、それとも私はここでいずれかのケースを見逃しましたか?

  • また、jQuery.setAttribute(attrName、untrusted_data)setAttribute(attrName、untrusted_data)は、属性名にURLコンテキストベースの属性(src、hrefなど)またはイベントハンドラー( src、hrefなど)が含まれていない場合にのみ、一般的に安全であると見なされることをどこかで読みました。 onClick、onMouseOverなど)。その場合、setAttribute( "href"、untrusted_data)を使用してhref属性を設定するにはどうすればよいですか?サーバー側からのencodeForHtmlAttribute(untrusted_data)は正しいアプローチ方法ですか?
  • ダイナミックHTMLの作成をどのように処理する必要がありますか。以下の例を考えてみましょう

<div id="divName1" onClick="copyData()">untrusted_data</div> <div id="divName2"></div>

function copyData()
{
  var divValue = jQuery("#divName1").html();
  jQuery("#divName2").html(divValue);/XSS Here
}

ここで達成したいのは、divName1からテキストを取得し、それをdivName2のコンテンツに貼り付けることです。上で書いたコードはXSSに対して脆弱です。これをに変更できます

jQuery( "#divName2")。text(divValue)

したがって、これによりエンコーディングが保証されますが、私が理解したように、クライアント側のエンコーディングは安全ではなく、サーバー側のエンコーディングのみを使用する必要があると言います。クライアント側のエンコーディングを使用せずにXSSセーフになるようにこれをどのように書く必要がありますか?私はここで少し混乱しています:(。これらの疑問を解決するために私を助けてください。

4

1 に答える 1

8

これは一度にたくさんの質問です。

クライアント側のエンコーディングが安全でないと見なされるのはなぜですか?

クライアント側のエンコーディングは、適切かつ一貫して行われている限り問題ありません。クライアント側のエンコーディングは、UTF-7攻撃のような文字エンコーディングレベルの攻撃について心配する必要がないため、多くの場合、バーが低くなります。

jQuery.val(untrusted_data)またはelement.value = untrusted_dataを使用して値を設定しようとしたときはいつでも、十分に安全であるように思われます。それで、それは本当にXSS安全ですか、それとも私はここでいずれかのケースを見逃しましたか?

untrusted_dataが文字列であり、値が設定されている要素がフローまたはブロック要素の通常のテキストノードであると仮定すると、問題ありません。値が割り当てられているノードが<script>要素内のテキストノード、URL、イベントハンドラー、スタイル属性ノード、またはに関連するものである場合、問題が発生する可能性があります<object>

また、jQuery.setAttribute(attrName、untrusted_data)とsetAttribute(attrName、untrusted_data)は、属性名にURLコンテキストベースの属性(src、hrefなど)またはイベントハンドラー( onClick、onMouseOverなど)。その場合は、

それは部分的に正しいです。他の属性には、および、およびにstyle関連する多くのもののような鋭いエッジがあります。<object><embed><meta>

属性についてよく知らない場合は、信頼できないデータに属性を公開しないでください。一般的に安全なのは、のようなテキストコンテンツを含む属性、またはのような値をtitle列挙した属性です。dir=ltrdir=rtl

より複雑な値をとる属性を扱うと、攻撃者が属性のよう-moz-bindingにあいまいなブラウザ拡張機能を悪用するリスクがありstyleます。

十分安全なようです

地雷は、踏むまでは安全なようです。

「安全に見える」ことから多くを結論付けることはできません。あなたは本当にそれを見て、何がうまくいかない可能性があるかを理解する必要があります、そしてあなたがうまくいかないことの完全な嵐があるときだけあなたが危険にさらされるように物事を整える必要があります(P(災害)= P(failure0)* P(failure1 )* ...)1つだけ問題が発生しても、リスクはありません(P(disaster)= P(failure0)+ P(failure1)* P(!failure0)+ ...)。

setAttribute( "href"、untrusted_data)を使用してhref属性を設定するにはどうすればよいですか?

プロトコルをホワイトリストに登録せずにそれを行わないでください。

if (!/^https?:\/\//i.test(untrusted_data) && !/^mailto:/i.test(untrusted_data)) {
  throw new Error('unsafe');
}

サーバー側からのencodeForHtmlAttribute(untrusted_data)は正しいアプローチ方法ですか?

いいえ。渡された値をエンコードするHTMLsetAttributeは冗長であり、セキュリティプロパティの保持には役立ちません。 <iframe srcdoc>最近の仕様変更の記憶が正しければ、その内容はHTMLであるため、まれな例外になる可能性があります。

ここで達成したいのは、divName1からテキストを取得し、それをdivName2のコンテンツに貼り付けることです。上で書いたコードはXSSに対して脆弱です。

HTMLをいじくり回さないでください。ブラウザの.innerHTMLゲッターはバグが多く、IEで値の区切り文字として機能するバックティックのようにエクスプロイトにつながることがあります。ノードを一方から他方に複製するだけです。以下のようなものがそれを行う必要があります:

var div1 = $('#divName1');
for (var child = div1[0].firstChild(); child; child = child.nextSibling) {
  $('#divName2').append([child.cloneNode(true)]);
}

これをに変更できます

jQuery("#divName2").text(divValue)

テキストコンテンツだけが必要な場合は問題ありません。

于 2012-11-20T08:10:45.980 に答える