5

生成されたHTMLに悪意のあるものが含まれていないことを確認するために、WMDエディターによって生成されたMarkdownのサーバー側スクラビングを実行する方法について、多くのスタックオーバーフローの質問があります(たとえば、ホワイトリスト、C#およびWMDマークダウンでのWMD制御によるXSSの防止およびサーバー側)このようなスクリプト:

<img onload="alert('haha');" 
   src="http://www.google.com/intl/en_ALL/images/srpr/logo1w.png" />

しかし、クライアント側の穴を塞ぐ良い方法も見つかりませんでした。もちろん、クライアント検証はサーバーでのスクラブ検証に代わるものではありません。誰もがクライアントのふりをして、厄介なMarkdownをPOSTできるからです。また、サーバー上のHTMLをスクラブしている場合、攻撃者は不正なHTMLを保存できないため、後で他のユーザーがHTMLを確認したり、Cookieが盗まれたり、不正なスクリプトによってセッションが乗っ取られたりすることはありません。したがって、WMDプレビューペインでもスクリプトなしのルールを適用する価値がない可能性があるという正当なケースがあります。

しかし、攻撃者が悪意のあるMarkdownをサーバーに取り込む方法を見つけたと想像してください(たとえば、別のサイトからの侵害されたフィード、またはXSSバグが修正される前に追加されたコンテンツ)。マークダウンをHTMLに変換するときに適用されるサーバー側のホワイトリストは、通常、その悪いマークダウンがユーザーに表示されるのを防ぎます。しかし、攻撃者が誰かにページを編集させることができた場合(たとえば、悪意のあるエントリにリンク切れがあったことを示す別のエントリを投稿し、誰かに修正を依頼することによって)、ページを編集する人は誰でもCookieが乗っ取られます。これは確かにコーナーケースですが、それでも防御する価値があるかもしれません。

また、クライアントプレビューウィンドウでサーバーが許可するのとは異なるHTMLを許可することはおそらく悪い考えです。

Stack Overflowチームは、WMDに変更を加えることで、この穴を塞いでいます。彼らはどうやってそれをしましたか?

[注:これはすでに理解していますが、JavaScriptのデバッグには注意が必要なので、同じことをしたいと思うかもしれない他の人を助けるために、ここで自分の質問に答えています]

4

2 に答える 2

6

考えられる修正の1つは、メソッドのwmd.jsにありpushPreviewHtml()ます。GitHub上のWMDのスタックオーバーフローバージョンの元のコードは次のとおりです。

if (wmd.panels.preview) {
    wmd.panels.preview.innerHTML = text; 
}

スクラブコードに置き換えることができます。これは、Stack Overflowがこの投稿に応答して使用するコードの適応です。これはタグのホワイトリストに制限され、IMGおよびA要素の場合は属性のホワイトリストに制限されます(特定の順序でも!)。Meta Stack Overflowの投稿を参照してください。StackOverflow、Server Fault、Super Userで許可されているHTMLタグは何ですか?ホワイトリストの詳細については。

注:このコードは確かに改善できます。たとえば、ホワイトリストに登録された属性を任意の順序で許可できます。また、mailto:URLも許可されていません。これは、インターネットサイトではおそらく良いことですが、独自のイントラネットサイトでは最善のアプローチではない可能性があります。

if (wmd.panels.preview) {

    // Original WMD code allowed JavaScript injection, like this:
    //    <img src="http://www.google.com/intl/en_ALL/images/srpr/logo1w.png" onload="alert('haha');"/>
    // Now, we first ensure elements (and attributes of IMG and A elements) are in a whitelist,
    // and if not in whitelist, replace with blanks in preview to prevent XSS attacks 
    // when editing malicious Markdown.
    var okTags = /^(<\/?(b|blockquote|code|del|dd|dl|dt|em|h1|h2|h3|i|kbd|li|ol|p|pre|s|sup|sub|strong|strike|ul)>|<(br|hr)\s?\/?>)$/i;
    var okLinks = /^(<a\shref="(\#\d+|(https?|ftp):\/\/[-A-Za-z0-9+&@#\/%?=~_|!:,.;\(\)]+)"(\stitle="[^"<>]+")?\s?>|<\/a>)$/i;
    var okImg = /^(<img\ssrc="https?:(\/\/[-A-Za-z0-9+&@#\/%?=~_|!:,.;\(\)]+)"(\swidth="\d{1,3}")?(\sheight="\d{1,3}")?(\salt="[^"<>]*")?(\stitle="[^"<>]*")?\s?\/?>)$/i;
    text = text.replace(/<[^<>]*>?/gi, function (tag) {
        return (tag.match(okTags) || tag.match(okLinks) || tag.match(okImg)) ? tag : ""
    })

    wmd.panels.preview.innerHTML = text;  // Original code 
}

また、この修正はGitHubのスタックオーバーフローバージョンのWMDには含まれていないことにも注意してください。明らかに、変更は後で行われ、GitHubにチェックインされていません。

更新:URLを入力したときにハイパーリンクが自動作成される機能を壊さないようにするには、以下のようにshowdown.jsにも変更を加える必要があります。

元のコード:

var _DoAutoLinks = function(text) {

    text = text.replace(/<((https?|ftp|dict):[^'">\s]+)>/gi,"<a href=\"$1\">$1</a>");

    // Email addresses: <address@domain.foo>

    /*
        text = text.replace(/
            <
            (?:mailto:)?
            (
                [-.\w]+
                \@
                [-a-z0-9]+(\.[-a-z0-9]+)*\.[a-z]+
            )
            >
        /gi, _DoAutoLinks_callback());
    */
    text = text.replace(/<(?:mailto:)?([-.\w]+\@[-a-z0-9]+(\.[-a-z0-9]+)*\.[a-z]+)>/gi,
        function(wholeMatch,m1) {
            return _EncodeEmailAddress( _UnescapeSpecialChars(m1) );
        }
    );

    return text;
}

修正されたコード:

var _DoAutoLinks = function(text) {
    // use simplified format for links, to enable whitelisting link attributes
    text = text.replace(/(^|\s)(https?|ftp)(:\/\/[-A-Z0-9+&@#\/%?=~_|\[\]\(\)!:,\.;]*[-A-Z0-9+&@#\/%=~_|\[\]])($|\W)/gi, "$1<$2$3>$4");
    text = text.replace(/<((https?|ftp):[^'">\s]+)>/gi, '<a href="$1">$1</a>');
    return text;
}
于 2010-05-14T20:59:21.823 に答える
2

サードパーティがスクリプトを提供することが不可能である限り、ローカルユーザーがページコンテキストでスクリプトを実行できるようにすることはセキュリティの問題ではありません。エディターがそれを行わなくても、ユーザーはjavascript:ページにいる間はいつでもURLを入力したり、Firebugなどを使用したりできます。

于 2010-05-14T21:02:26.700 に答える