Allineare del redattore WMD anteprima HTML con la validazione lato server HTML (codice JavaScript per esempio non incluso)

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

Domanda

Ci sono molte domande di overflow dello stack (ad esempio whitelist, impedendo XSS con controllo di WMD in C # e WMD Markdown e lato server ) su come fare lato server lavaggio di Markdown prodotte dal redattore WMD per garantire il codice HTML generato non contiene script dannoso, in questo modo:

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

Ma non ho trovato un buon modo per tappare il buco sul lato client troppo. validazione client non è un sostituto per il lavaggio di convalida sul server, naturalmente, dal momento che chiunque può fingere di essere un cliente e post che brutto Markdown. E se si sta lavando il codice HTML sul server, un attaccante non può salvare il cattivo HTML in modo che nessun altro sarà in grado di vedere in un secondo momento e hanno i loro biscotti rubati o sessioni dirottato dallo script male. Quindi c'è una causa valida da fare che non può essere la pena di far rispettare le regole no-script nel riquadro di anteprima WMD troppo.

Ma immaginate un attaccante ha trovato un modo per ottenere dannoso Markdown sul server (ad esempio un feed compromesso da un altro sito, o contenuti aggiunti prima di un bug XSS è stato fissato). Il server-side whitelist applicata quando si traduce in HTML Markdown normalmente evitare così male Markdown venga mostrato agli utenti. Ma se l'utente malintenzionato potrebbe ottenere qualcuno di modificare la pagina (ad esempio con la pubblicazione di un'altra voce dicendo la voce maligno aveva un collegamento interrotto e chiedere a qualcuno di risolvere il problema), allora chiunque cura la pagina ottiene loro biscotti dirottato. Questo è certamente un caso d'angolo, ma ancora può valere la pena difendere contro.

Inoltre, è probabilmente una cattiva idea permettere la finestra di anteprima del client per permettere diverso HTML che il vostro server consentirà.

Il team di Stack Overflow ha tappato questo buco apportando modifiche alle WMD. Come hanno fatto?

[NOTA: Ho già capito questo, ma è richiesto il debug qualche ingannevole JavaScript, quindi sto rispondendo alla mia domanda proprio qui per aiutare gli altri che potrebbero voler fare THS stessa cosa].

È stato utile?

Soluzione

Una possibile soluzione è in wmd.js, nel metodo pushPreviewHtml(). Ecco il codice originale dal Stack Overflow versione di ADM su GitHub :

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

È possibile sostituirlo con un codice di lavaggio. Ecco un adattamento del codice che utilizza Stack Overflow in risposta a questo post , che limita ad una whitelist di tag, e per gli elementi IMG e a, limita ad una whitelist di attributi (e in un ordine specifico troppo!). Vedi il post Meta Stack Overflow Quali tag HTML sono ammessi su Stack Overflow, server Fault, e Super User? per più informazioni whitelist.

Nota: questo codice può certamente essere migliorata, per esempio per consentire alla white list attributi in qualsiasi ordine. Inoltre esclude dal finanziamento mailto:. URL che è probabilmente una buona cosa sui siti Internet, ma sul proprio sito intranet potrebbe non essere l'approccio migliore

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 
}

Si noti inoltre che questa correzione non è nel Stack Overflow versione di ADM su GitHub - chiaramente il cambiamento è stato effettuato entro e non controllato di nuovo in GitHub.

UPDATE: al fine di evitare di rompere la caratteristica in cui i collegamenti ipertestuali sono creati automaticamente quando si digita un URL, è anche sarà necessario apportare modifiche a showdown.js, come di seguito:

Codice originale:

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;
}

Codice fisso:

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;
}

Altri suggerimenti

Non è un problema di sicurezza per consentire all'utente locale di eseguire script nel contesto di pagina finché è impossibile per terze parti per fornire lo script. Senza l'editor a farlo, l'utente può sempre inserire un URL javascript: mentre sulla vostra pagina oppure utilizzare Firebug o qualcosa di simile.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top