一般公開されるユーザー生成のhtmlコンテンツを処理する最良の方法は何ですか?

StackOverflow https://stackoverflow.com/questions/1608758

  •  05-07-2019
  •  | 
  •  

質問

私のWebアプリケーションでは、Stackoverflowと同様に、ユーザーが生成したコンテンツを一般消費向けに投稿できます。

これを渡すためのベストプラクティスは何ですか?

ユーザー生成コンテンツを処理するための現在の手順は次のとおりです。

  1. MarkItUp を使用してユーザーを許可します htmlをフォーマットする簡単な方法。

  2. ユーザーが送信した後 変更 HTML 消毒剤 (スクロールして bottem)ホワイトリストを使用 アプローチ。

  3. 消毒プロセスに ユーザーが作成したコンテンツを削除しましたI コンテンツを保存しないでください。そして私は・・・それから私は 修正されたコンテンツをそこに返します 警告メッセージ、"一部違法 検出されたコンテンツタグと 作業を再確認して削除し、 再試行してください。"

  4. コンテンツが 消毒プロセスをきれいに保存します に生のhtmlコンテンツ データベース。

  5. クライアントにレンダリングするときは dbから生のhtmlを渡す ページ。

役に立ちましたか?

解決

これは完全に合理的なアプローチです。通常のアプリケーションでは、これで十分です。

ホワイトリストの未加工HTMLの最も難しい部分は、 style 属性と embed / object です。誰かがCSSスタイルを、そうでなければ信頼できないフォーマットされたテキストのブロック、または埋め込まれたYouTubeビデオに入れたいと思う正当な理由があります。この問題は、フィードで最もよく発生します。フィードエントリに含まれるテキストの任意のブロックを信頼することはできませんが、たとえば、CSSやフラッシュビデオを強調する構文を削除したくはありません。 CSSにはIEの動作などの危険なものが含まれている可能性があるため、 style 属性をそのままにしておく場合は、CSSを解析する必要があります。また、 embed / オブジェクトホスト名をホワイトリストに登録する必要がある場合があります。

補遺:

最悪のシナリオでは、HTMLが見えているすべてをエスケープすると、ユーザーエクスペリエンスが非常に低下する可能性があります。ホワイトリストを使用してDOMを通過するには、HTML5パーサーのいずれかを使用することをお勧めします。これは、サニタイズされた出力をユーザーにどのように提示するかという点ではるかに柔軟です。次のようなこともできます:

<div class="sanitized">
  <div class="notice">
    This was sanitized for security reasons.
  </div>
  <div class="raw"><pre>
    &lt;script&gt;alert("XSS!");&lt;/script&gt;
  </pre></div>
</div>

次に .raw をCSSで非表示にし、jQueryを使用してクリックハンドラーを .sanitized div にバインドします。 code> .raw および .notice

CSS:

.raw {
  display: none;
}

jQuery:

$('.sanitized').click(function() {
  $(this).find('.notice').toggle();
  $(this).find('.sanitized').toggle();
});

他のヒント

ホワイトリストは良い動きです。ブラックリストのソリューションは、すべてを考えることができないため、必要以上に許可されがちです。私はブラックリスト(たとえば、コードプロジェクト)を使用するいくつかの属性を見てきましたが、それらがすべてをキャッチできた場合、一般的にコードの文字を置き換えるなどの追加の問題が発生するため、最初に手動で復元しないと使用できません。

最も安全な方法は次のとおりです。

  1. すべてのテキストをHTMLエンコードします。

  2. 許可されたタグと属性のセットを照合し、それらをデコードします。

正規表現を使用すると、各開始タグに終了タグが必要になるため、閉じられていないタグがページを混乱させることはありません。

10行のコードのようなものでこれを行うことができるはずなので、リンクしたコードは非常に複雑に見えます。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top