Aligner le HTML aperçu de l'éditeur ADM avec validation côté serveur HTML (code JavaScript par exemple pas intégré)

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

Question

Il y a beaucoup de questions dépassement de la pile (par exemple whitelisting, ce qui empêche le contrôle XSS avec armes de destruction massive en C # et armes de destruction massive Markdown et côté serveur ) sur la façon de faire frotter de démarquage côté serveur produit par l'éditeur ADM pour assurer le code HTML généré ne contient pas de script malveillant, comme ceci:

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

Mais je n'ai pas trouvé un bon moyen de boucher le trou sur le côté client aussi. la validation du client ne remplace pas pour la validation de lavage sur le serveur bien sûr, puisque tout le monde peut faire semblant d'être un client et POST vous méchant Markdown. Et si vous frotter le HTML sur le serveur, un attaquant ne peut pas sauver le mauvais HTML pour que personne ne pourra le voir plus tard et ont leurs cookies volés ou détournés par des sessions du mauvais script. Donc, il y a un cas valable à fait qu'il ne peut pas être utile dans l'application du volet d'aperçu des ADM règles sans trop de script.

Mais imaginez un attaquant a trouvé un moyen d'obtenir Markdown malveillant sur le serveur (par exemple un flux compromis d'un autre site ou contenu ajouté avant un bug XSS a été fixé). Votre côté serveur whitelist appliqué lors de la traduction démarquage HTML empêcherait normalement que la mauvaise Markdown d'être montré aux utilisateurs. Mais si l'attaquant pourrait trouver quelqu'un pour modifier la page (par exemple en affichant une autre entrée disant l'entrée malicieuse avait un lien brisé et demander à quelqu'un de le réparer), puis tous ceux qui édite la page reçoit leurs cookies détourné. Ceci est certes un cas d'angle, mais il peut encore se défendre contre une valeur.

En outre, il est probablement une mauvaise idée pour permettre à la fenêtre de prévisualisation du client pour permettre à différents HTML que votre serveur permettra.

La pile équipe de débordement a bouché ce trou en apportant des modifications aux armes de destruction massive. Comment ont-ils le faire?

[NOTE: Je l'ai déjà compris cela, mais il a nécessité quelques débogage JavaScript difficile, alors je réponds à ma propre question ici pour aider les autres qui peuvent vouloir faire ths même chose].

Était-ce utile?

La solution

Une solution possible est wmd.js, dans la méthode pushPreviewHtml(). Voici le code original du Stack Overflow la version d'ADM sur GitHub :

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

Vous pouvez le remplacer par un code de lavage. Voici une adaptation du code Stack Overflow utilise en réponse à ce message , ce qui limite à une liste blanche des balises et des éléments IMG et a, limite à une liste blanche des attributs (et dans un ordre spécifique aussi!). Voir le message Stack Overflow Meta BALISES HTML sont autorisés sur le débordement de pile, de pannes de serveur et Super User? pour plus d'informations sur la liste blanche.

Remarque: ce code peut certainement être améliorée, par exemple pour permettre la liste blanche des attributs dans un ordre quelconque. Il a également mailto exclut du financement. URL qui est probablement une bonne chose sur les sites Internet mais sur votre propre site intranet, il ne peut pas être la meilleure approche

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 
}

Notez également que ce correctif est pas dans le Stack Overflow la version des ADM sur GitHub - clairement le changement a été fait plus tard et non réintégrée dans GitHub.

Mise à jour: afin d'éviter de casser la fonction où des liens sont créés automatiquement lorsque vous tapez une URL, vous devez aussi apporter des modifications à showdown.js, comme ci-dessous:

Code d'origine:

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

Code fixe:

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

Autres conseils

Il est pas un problème de sécurité pour permettre à l'utilisateur local d'exécuter des scripts dans le contexte de la page tant qu'il est impossible pour une tierce partie de fournir le script. Sans l'éditeur de le faire, l'utilisateur peut toujours entrer une URL javascript: pendant votre page ou Firebug ou quelque chose de similaire.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top