2010-05-14 7 views
5

Ci sono molte domande di overflow dello stack (ad esempio Whitelisting, preventing XSS with WMD control in C# e WMD Markdown and server-side) su come fare di lavaggio sul lato server di Markdown prodotto da l'editor WMD per garantire il codice HTML generato non contiene script dannosi, come questo:anteprima allineamento del redattore WMD HTML con la convalida HTML lato server (ad esempio, nessun codice JavaScript incorporato)

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

Ma non ho trovato un buon modo per chiudere il foro sul lato client troppo. La convalida del client non sostituisce ovviamente la convalida di scrubbing sul server, dal momento che chiunque può fingere di essere un cliente e POST you mark you brutto. E se stai tagliando l'HTML sul server, un utente malintenzionato non può salvare il codice HTML errato in modo che nessun altro possa vederlo più tardi e venga rubato i cookie o le sessioni vengano dirottate dallo script non valido. Quindi c'è un caso valido da fare che potrebbe non valere la pena applicare le regole senza script anche nel riquadro di anteprima WMD.

Ma immagina che un utente malintenzionato abbia trovato un modo per ottenere Markdown dannoso sul server (ad esempio, un feed compromesso da un altro sito o contenuto aggiunto prima della correzione di un bug XSS). La tua whitelist lato server applicata quando si traduce markdown in HTML normalmente impedirebbe che quel Markdown errato venga mostrato agli utenti. Ma se l'autore dell'attacco può convincere qualcuno a modificare la pagina (ad es. Pubblicando un'altra voce dicendo che l'ingresso malevolo ha un link interrotto e chiedendo a qualcuno di risolverlo), allora chiunque modifica la pagina ottiene il dirottamento dei suoi cookie. Questo è certamente un caso isolato, ma potrebbe valere la pena di difendersi.

Inoltre, è probabilmente una cattiva idea consentire alla finestra di anteprima del client di consentire HTML diversi da quelli consentiti dal server.

Il team Overflow dello stack ha inserito questo foro apportando modifiche a WMD. Come hanno fatto?

[NOTA: l'ho già capito, ma ha richiesto un po 'complicato debug di JavaScript, quindi sto rispondendo alla mia domanda qui per aiutare gli altri che potrebbero voler fare la stessa cosa].

risposta

6

Una possibile correzione è in wmd.js, nel metodo pushPreviewHtml(). Ecco il codice originale dal Stack Overflow version of WMD on GitHub:

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

È possibile sostituirlo con un codice di lavaggio. Ecco un adattamento del codice che Stack Overflow utilizza in response to this post, che limita a una lista bianca di tag, e per gli elementi IMG e A, limita a una lista bianca di attributi (e anche in un ordine specifico!). Vedere l'overflow di Meta Stack What HTML tags are allowed on Stack Overflow, Server Fault, and Super User? per ulteriori informazioni sulla whitelist.

Nota: questo codice può essere sicuramente migliorato, ad es. per consentire gli attributi autorizzati in qualsiasi ordine. Inoltre, non consente mailto: URL che sono probabilmente una buona cosa sui siti Internet ma sul proprio sito intranet potrebbero 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 version of WMD on GitHub - chiaramente il cambiamento è stato fatto tardi e non controllato di nuovo in GitHub.

AGGIORNAMENTO: per evitare di rompere la funzionalità in cui i collegamenti ipertestuali vengono creati automaticamente quando si digita un URL, è anche necessario apportare modifiche allo 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: <[email protected]> 

    /* 
     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; 
} 
+0

Non sono convinto che questo sia qualcosa che deve essere risolto. Sembra una soluzione alla ricerca di un problema. Forse il motivo per cui non vedi questo codice nella versione StackOverflow di WMD è perché non esiste, perché non è necessario. –

+2

Sì, non sono nemmeno convinto che sia necessario. Detto questo, i ragazzi di StackOverflow.com lo hanno implementato per garantire che l'anteprima non abbia mai generato HTML che il loro validatore lato server non avrebbe accettato. Sembra ragionevole, anche se non sono d'accordo con una priorità terribilmente alta. Vedi http://meta.stackexchange.com/questions/1227/preview-should-match-the-posted-view per maggiori dettagli sul perché SO ha fatto. BTW Ho appena modificato la mia domanda per allinearmi alla ragione effettiva per cui SO voleva farlo. –

+0

Potresti AJAX postare l'HTML e recuperare l'HTML sanitizzato dal server, per ottenere un'anteprima perfetta. – ceejayoz

2

Non è un problema di sicurezza per consentire all'utente locale di eseguire script nella contesto di pagina finché è impossibile per qualsiasi terza parte fornire lo script. Senza l'editor che lo fa, l'utente può sempre inserire un URL mentre sulla tua pagina o usare Firebug o qualcosa di simile.

+0

inizialmente ero d'accordo con te, ma ho trovato un caso interessante: se ci fosse un altro modo per un attaccante di ottenere markdown compromesso sul server, allora questo problema di anteprima WMD sarebbe pericoloso. Se un utente malintenzionato potrebbe richiedere a un moderatore del sito di modificare una pagina errata (ad esempio per cancellare un collegamento interrotto), potrebbe potenzialmente assumere il controllo dell'intero sito. È vero, t'd essere facile da sconfiggere scrubbing markdown sul server prima di inviare alla pagina di modifica, ma la convalida dell'output viene spesso ignorata. Questo è certamente un caso isolato, ma potrebbe valere la pena di difendersi da un sito sicuro. –

Problemi correlati