4

そのため、json を介して外部の信頼できないソースから html を受信して​​います。次のように div コンテナに html を表示したい:

$('#container').html(dangerousHTMLCode);

最も重要なJavaScriptインジェクションをどのように防ぐことができますか.2番目は一般的にページのスタイルを変更することです. これはすべてクライアント側です。コンテナーの div は、コンテンツの高さに合わせて柔軟な高さにする必要があります (一部の iframe ソリューションを除外する可能性があります)。

更新: 目標は、HTML からすべての JavaScript と CSS を取り除くことです。これには、dom アイテムの属性 (style=""、onclick="" など) に存在する js および css が含まれます。

4

2 に答える 2

2

OK、これに対する私の最初の試みは失敗でした。Jan Dvorakのコメントに同意します。これは、サーバー側プロキシのXSSツールを使用して行うのが最善の方法です。特に、クロスサイトリクエストを実行しているため、何らかのプロキシを使用する必要があるためです。 JSONPを使用している場合は、すでにすべてが失われています。

しかし、質問はこれを行うためのjQueryの方法を求めていたので...

理想的には、JavaScriptで記述されたHTMLパーサーを見つけ、それを使用して要素ツリーを構築し、安全な属性のホワイトリストに一致しなかった要素または属性を削除します。

私はそのようなパーサーを認識しておらず、パーサーを備えたブラウザーを使用しているので、それを使用してみます。ただし、パーサーはjavascriptエンジンとHTTPクライアントなどに接続されていることに注意する必要があります。

まず、最初の試みへのフィードバックで指摘されたように、一部のイベントはDOmの挿入前に実行される可能性があるため、DOM要素を作成する前にいくつかの作業を行う必要があります。少なくとも、DOMオブジェクトが作成される前にonX属性が解析されないようにする必要があります。また、一般的にプリロードとの干渉を実行することもお勧めします。そのために、簡単なテキスト変換を行いましょう。

var xmlNameStartChars = "a-zA-Z_\\u00c0-\\u00d6\\u00d8-\\u00f6\\u00f8-\\u02ff\\0370-\\u037d\\u037f-\\u1fff\\u200c\\u200d\\u2070-\\u2218f\\u2c00-\\u2fef\\u3001-\\udbbf\\udc00-\\udfff\\uf900-\\ufdcf\\ufdf0-\\ufffd";
var xmlNsPfx = "[" + xmlNameStartChars + "][-.0-9\\u00b7\\u0300-\\u036f\\u203f-\\u2040" + xmlNameStartChars + "]*:";
var tagStartRE = new RegExp("<\\/?(" + xmlNsPfx + ")?", "g");
var tagStartDeZRE = new RegExp("(<\\/(" + xmlNsPfx + ")?)z", "g");
dangerousHTMLCode = dangerousHTMLCode.replace(/on/gi, "z$&"); // run interference with onX
// run interference with preloading
// But don't interfere with namespaces
dangerousHTMLCode = dangerousHTMLCode.replace(/<\/?(\w*:)?/g, "$&z");

これで、DOMツリーを安全に構築できるように最善を尽くしました。ただし、この最善の努力は安全性を保証するものではないことに注意してください。過去、現在、または将来のブラウザやプラグインのバグを中心に、私が考慮していない攻撃が行われる可能性があります。特に懸念されるのは、この時点で干渉しなければならないほど危険な属性は「オン」で始まると仮定したことです。そうだと思いますが、100%自信がありません。

自己責任で続行してください

Janが私の最初の試みに対するコメントで指摘したように、ホワイトリストのアプローチはおそらくブラックリストのアプローチよりも優れています。ホワイトリストに登録された要素のかなり基本的なリストから始め、好みに合わせて追加/削除します。zテキスト操作でも接頭辞が付けられるので、接頭辞としてsを付けます。

var wlElements = "zdiv, zspan, zem, zstrong, zp, za, zimg, ztable, zthead, ztbody, ztfoot, ztr, zth, ztd";
var nonWlSelector = ":not(" + wlElements + ")";
var dangerousDOM = $("<div/>").html(dangerousHTMLCode);
dangerousDOM.find(nonWlSelector).remove();

楽しい部分として、危険な属性を削除する必要があります。今回は、ホワイトリストに登録したいすべての属性を考えるのが面倒だったため、ブラックリストに登録しました...しかし、srcとhrefでURLスキームをホワイトリストに登録しています。これは、「javascript:」だけでなく、潜在的に安全ではありません。」一部のブラウザでは、少なくともvbscript:」と「livescript:」は危険です。属性をホワイトリストに登録する必要があります。たとえば、「オン」で始まらないスクリプト属性について、私が忘れたり、知らなかったりする可能性があります。ブルートフォースDOMウォークを実行せずに「悪い」属性を見つける方法を見つけられなかったので、それを実行しましょう。

var badAttrs = /^(.*:)(zon|style|background)/i;
var suspectAttrs = /^(.*:)(src|href)$/i;
var goodSchemes = /^\s*([^:]*$|ftp:|tel:|https?:)/i;
function processAttributes(element) {
    var toRemove = [];
    var attrs = element.attributes;
    for (var i = 0; i < attrs.length; i++) {
        var name = attrs[i].name, val = attrs[i].value;
        if (badAttrs.test(name) || (suspectAttr.test(name) && !goodSchemes.test(val)) {
            toRemove.push(attrs[i].name);
        }
    }
    while (toRemove.length) {
        element.removeAttribute(toRemove.pop());
    }
}

// Start walking from the root of our DOM fragment
var root = dangerousDOM[0];
var elements = [root];

// Walk until we have no more elements, processing their attributes and adding their children
while (elements.length) {
    var elem = elements.pop();
    if (elem.hasAttributes()) {
        processAttributes(elem);
    }

    // Find children of this element and queue them up
    child = elem.firstChild;
    while (child) {
        if (child.nodeType == 1) {
            // It's an element
            elements.push(child);
        }
        child = child.nextSibling;
    }
}

これで、最初に行ったテキスト操作を元に戻し、フラグメントを挿入する準備が整いました。繰り返しになりますが、これをより安全にするための最善の努力は、今日機能する攻撃を考慮することができず、将来のブラウザ/プラグインのバグに対する攻撃を許可する可能性があります。したがって、繰り返しになりますが、自己責任で続行してください。

var lessDangerousHtml = dangerousDOM.html();
lessDangerousHtml = lessDangerousHtml.replace(/z(on)/gi, "$1");
lessDangerousHtml = lessDangerousHtml.replace(tagStartDeZRE, "$1");
$("#container").html(lessDangerousHtml);

建設的な批判をしてくれたt.nieseに感謝します。

于 2013-03-16T16:18:04.377 に答える