83

クロス ドメイン リクエストを介して読み込まれた外部リソースを表示し、「安全な」コンテンツのみを表示するようにする必要があります。

Prototype のString#stripScriptsを使用して、スクリプト ブロックを削除できます。ただし、onclickorなどのハンドラonerrorはまだ存在します。

少なくともできるライブラリはありますか

  • スクリプト ブロックを取り除きます。
  • DOM ハンドラーを強制終了します。
  • ブラック リストのタグを削除します (例:embedまたはobject)。

JavaScript 関連のリンクや例はありますか?

4

10 に答える 10

113

2016 年の更新: Caja サニタイザーに基づくGoogle Closureパッケージが追加されました。

よりクリーンな API があり、最新のブラウザーで利用可能な API を考慮して書き直され、Closure Compiler とのやり取りが改善されています。


恥知らずなプラグイン:徹底的にレビューされたクライアント側の HTML サニタイザーについては、caja/plugin/html-sanitizer.jsを参照してください。

ブラックリストではなくホワイトリストに登録されていますが、ホワイトリストはCajaWhitelistsに従って構成可能です


すべてのタグを削除する場合は、次の手順を実行します。

var tagBody = '(?:[^"\'>]|"[^"]*"|\'[^\']*\')*';

var tagOrComment = new RegExp(
    '<(?:'
    // Comment body.
    + '!--(?:(?:-*[^->])*--+|-?)'
    // Special "raw text" elements whose content should be elided.
    + '|script\\b' + tagBody + '>[\\s\\S]*?</script\\s*'
    + '|style\\b' + tagBody + '>[\\s\\S]*?</style\\s*'
    // Regular name
    + '|/?[a-z]'
    + tagBody
    + ')>',
    'gi');
function removeTags(html) {
  var oldHtml;
  do {
    oldHtml = html;
    html = html.replace(tagOrComment, '');
  } while (html !== oldHtml);
  return html.replace(/</g, '&lt;');
}

人々は、要素を作成し、割り当ててからorinnerHTMLを取得し、その中のエンティティをエスケープできると言うでしょう。そんなことしたらダメ。ノードが DOM にアタッチされていない場合でもハンドラーを実行するため、XSS インジェクションに対して脆弱です。innerTexttextContent<img src=bogus onerror=alert(1337)>onerror

于 2009-01-10T00:19:59.017 に答える
40

Google Caja HTML サニタイザーは、 Web ワーカーに埋め込むことで「Web 対応」にすることができます。サニタイザーによって導入されたすべてのグローバル変数はワーカー内に含まれ、処理は独自のスレッドで行われます。

Web ワーカーをサポートしていないブラウザーの場合、サニタイザーが機能する別の環境として iframe を使用できます。Timothy Chien は、iframeを使用して Web ワーカーをシミュレートするためのポリフィルを持っているので、その部分は私たちのために行われます。

Caja プロジェクトには、 Caja をスタンドアロンのクライアント側サニタイザーとして使用する方法に関する wiki ページがあります。

  • ソースをチェックアウトし、実行してビルドしますant
  • ページにhtml-sanitizer-minified.jsまたはを含めるhtml-css-sanitizer-minified.js
  • 電話html_sanitize(...)

ワーカー スクリプトは、次の手順に従うだけで済みます。

importScripts('html-css-sanitizer-minified.js'); // or 'html-sanitizer-minified.js'

var urlTransformer, nameIdClassTransformer;

// customize if you need to filter URLs and/or ids/names/classes
urlTransformer = nameIdClassTransformer = function(s) { return s; };

// when we receive some HTML
self.onmessage = function(event) {
    // sanitize, then send the result back
    postMessage(html_sanitize(event.data, urlTransformer, nameIdClassTransformer));
};

(simworker ライブラリを機能させるにはもう少しコードが必要ですが、この説明では重要ではありません。)

デモ: https://dl.dropbox.com/u/291406/html-sanitize/demo.html

于 2012-07-05T11:31:06.563 に答える
21

クライアントを決して信用しないでください。サーバー アプリケーションを作成している場合は、クライアントが常に不衛生で悪意のあるデータを送信すると想定してください。トラブルを未然に防ぐための鉄則です。可能であれば、サーバー コードですべての検証とサニテーションを行うことをお勧めします。おそらく、サーバー側の Web アプリケーションをクライアント側コードのプロキシとして使用して、サードパーティからフェッチし、クライアント自体に送信する前にサニテーションを行うことができますか?

[編集] 申し訳ありませんが、質問を誤解しました。しかし、私は私のアドバイスを支持します。ユーザーに送信する前にサーバーをサニタイズすると、おそらくユーザーはより安全になります。

于 2009-01-10T00:53:23.757 に答える
12

どこかのブラウザがブラックリストから逃れるためにつまずく可能性のある奇妙なタイプの不正なマークアップをすべて予測することはできないので、ブラックリストに登録しないでください。スクリプト/埋め込み/オブジェクトとハンドラーだけでなく、削除する必要のある構造もたくさんあります。

代わりに、HTMLを階層内の要素と属性に解析してから、可能な限り最小限のホワイトリストに対してすべての要素と属性の名前を実行してください。また、通過させたURL属性をホワイトリストと照合します(JavaScriptよりも危険なプロトコルがあることに注意してください:)。

入力が整形式のXHTMLである場合、上記の最初の部分ははるかに簡単です。

HTMLサニタイズの場合と同様に、それを回避する他の方法を見つけることができる場合は、代わりにそれを行ってください。多くの潜在的な穴があります。主要なウェブメールサービスがこの数年経ってもまだエクスプロイトを見つけているとしたら、何があなたをより良くできると思いますか?

于 2008-11-17T15:26:35.473 に答える
0

フレームワークを生活から切り離すことをお勧めします。長期的には物事が非常に簡単になります。

cloneNode: ノードのクローンを作成すると、そのすべての属性とその値がコピーされますが、イベント リスナーはコピーされませ

https://developer.mozilla.org/en/DOM/Node.cloneNode

以下はテストされていませんが、私はツリーウォーカーをしばらく使用しており、JavaScript の最も過小評価されている部分の 1 つです。クロールできるノード タイプのリストを次に示します。通常はSHOW_ELEMENTまたはSHOW_TEXTを使用します。

http://www.w3.org/TR/DOM-Level-2-Traversal-Range/traversal.html#Traversal-NodeFilter

function xhtml_cleaner(id)
{
 var e = document.getElementById(id);
 var f = document.createDocumentFragment();
 f.appendChild(e.cloneNode(true));

 var walker = document.createTreeWalker(f,NodeFilter.SHOW_ELEMENT,null,false);

 while (walker.nextNode())
 {
  var c = walker.currentNode;
  if (c.hasAttribute('contentEditable')) {c.removeAttribute('contentEditable');}
  if (c.hasAttribute('style')) {c.removeAttribute('style');}

  if (c.nodeName.toLowerCase()=='script') {element_del(c);}
 }

 alert(new XMLSerializer().serializeToString(f));
 return f;
}


function element_del(element_id)
{
 if (document.getElementById(element_id))
 {
  document.getElementById(element_id).parentNode.removeChild(document.getElementById(element_id));
 }
 else if (element_id)
 {
  element_id.parentNode.removeChild(element_id);
 }
 else
 {
  alert('Error: the object or element \'' + element_id + '\' was not found and therefore could not be deleted.');
 }
}
于 2012-07-04T05:58:16.007 に答える