This is an old revision of the document!


Work in progress. Ce ne sont que des notes de travile, je ne pense pas avoir encore fait le tour de la question. Je dois essayer de systématiser un peu plus la description des chaînes.

Chaînes dangereuses

À partir du recensement effectué sur la page : http://ha.ckers.org/xss.html on peut synthétiser quelques informations sur les chaînes de caractères pouvant être sources de cross-site scripting (XSS dans la suite).

Les XSS ont la structure suivante :

  • Un contexte encapsulant la chaîne, servant souvent à permettre d'écrire la chaîne sous une forme innoffensive. Dans ces cas, c'est la combinaison contexte - chaîne qui est dangereuse;
  • La chaîne de caractère elle-même.

Sauf exceptions (présentées plus bas), la chaîne peut être décomposée ainsi :

  • “<” un chevron ouvrant de balise ;
  • une chaîne de caractère contenant un nom de balise, classique ou non ;
  • un ou plusieurs séparateurs ;
  • une chaînes de caractère introduisant le script ;
  • le script lui-même.

C'est comme un médicament : il faut un principe actif et un excipient. Le principe actif est la molécule qui va agir, mais elle est inutile si elle n'est pas mélangée à l'excipient chargé de l'amener à bon port.

Le rôle du contexte est de faire passer les barrières au code hostile.

Exemple : une bonne vieille balise XML qui contient une section CDATA avec des balises et un script encodés en HTML. tout ça analysé par le navigateur donnera une script interprété. Mais si on se contente d'une recherche sur une chaîne genre “<SCRIPT*”, on n'obtiendra jamais de résultat.

L'exemple ci-dessous a l'air de marcher sous IE 6 et 7. Pas sur Firefox ;)

<XML ID=I><X><C><![CDATA[<IMG SRC="javas]]><![CDATA[cript:alert('XSS');">]]>
</C></X></xml><SPAN DATASRC=#I DATAFLD=C DATAFORMATAS=HTML></SPAN>

Ça peut aussi tout simplement être des espaces vides, ou la fermeture d'une autre balise (</title> par exemple).

Les chevrons, notamment, peuvent être encodés (couramment en HTML “&lt;”) pour ne pas être repérés par les expressions régulières. L'auteur de la page propose la liste suivante d'encodages différents pour le chevron ouvrant, en combinant HTML et javascript (en UTF-8). Il précise que “la plupart ne donneront rien, mais certains peuvent être correctement interprétées suivant certaines circonstances.”

  • <
  • %3C
  • &lt
  • &lt;
  • &LT
  • &LT;
  • &#60
  • &#060
  • &#0060
  • &#00060
  • &#000060
  • &#0000060
  • &#60;
  • &#060;
  • &#0060;
  • &#00060;
  • &#000060;
  • &#0000060;
  • &#x3c
  • &#x03c
  • &#x003c
  • &#x0003c
  • &#x00003c
  • &#x000003c
  • &#x3c;
  • &#x03c;
  • &#x003c;
  • &#x0003c;
  • &#x00003c;
  • &#x000003c;
  • &#X3c
  • &#X03c
  • &#X003c
  • &#X0003c
  • &#X00003c
  • &#X000003c
  • &#X3c;
  • &#X03c;
  • &#X003c;
  • &#X0003c;
  • &#X00003c;
  • &#X000003c;
  • &#x3C
  • &#x03C
  • &#x003C
  • &#x0003C
  • &#x00003C
  • &#x000003C
  • &#x3C;
  • &#x03C;
  • &#x003C;
  • &#x0003C;
  • &#x00003C;
  • &#x000003C;
  • &#X3C
  • &#X03C
  • &#X003C
  • &#X0003C
  • &#X00003C
  • &#X000003C
  • &#X3C;
  • &#X03C;
  • &#X003C;
  • &#X0003C;
  • &#X00003C;
  • &#X000003C;
  • \x3c
  • \x3C
  • \u003c
  • \u003C

La liste suivante contient les balises pouvant introduire un attribut contenant un script.

  • SCRIPT
  • IMG
  • BODY
  • IFRAME
  • FRAMESET, FRAME
  • INPUT
  • LAYER
  • BGSOUND
  • BR
  • LINK (rel=“stylesheet”, ref=“<script>”)
  • STYLE
  • TABLE
  • TD
  • META
  • DIV
  • BASE
  • OBJECT
  • EMBED
  • NIMPORTEQUOI : dans certains cas, le nom de la balise n'a pas d'importance. Il ne sert qu'à introduire la suite (en général dans un attribut “style”).

On peut aussi bien tous les interdire si on veut, ou bien en interdire la majorité et ne traiter les cas particuliers que pour ceux qu'on veut laisser utilisables.

En règle générale, il ne faut plutôt rechercher une balise ouvrante et en rester là. Il est en effet possible, dans de nombreux cas, de ne pas fermer une balise, et son code sera tout de même interprété !

Ce qu'il y a après la chaîne “chevron ouvrant+balise” (“<SCRIPT”, par exemple) peut fortement varier. La balise peut être fermée et c'est son contenu qui est dangereux, ou bien elle est encore ouverte et on doit chercher le script dans ses attributs. Il existe même des méthodes permettant de faire croire que la balise est ouverte alors qu'on va la fermer juste après.

Voici un florilège de “trucs qu'on peut trouver apès une balise” :

  • '>' une chevron fermant. Après une balise script, par exemple;
  • ' ' un espace. pourra être suivi d'un attribut src ou de n'importe quel autre attribut, ou bien d'un espace, etc…
  • une tabulation
  • divers caractères encodé “&#x09;” (tabulation) “&#x0A;” (saut de ligne) “&#x0D;” (retour chariot). Ces caractères permettent par exemple d'écrire le XXS avec un caractère par ligne.
  • le caractère nul (\0) permet, s'il est in jecté par des outils comme "Burp proxy" (quoi que ça puisse être) permettent de masquer passer les filtres. Bêtement écrits (dans un champ texte), ils semblent casser le code javascript.
  • '“”“' : trois guillemets. Permet de décaler un ouverture/fermeture de script
  • “\BLABLA” : une chaîne qui n'a pas de sens précédée d'un caractère qui n'est ni une lettre ni un chiffre. Certains navigateurs vont considérer qu'un caractère qui n'est ni une lettre ni un chiffre est équivalent à un espace dans un nom de balise HTML.
  • n'importe quel caractère de valeur décimale entre 1 et 32 peut être placé avant le javascript
  • tous ces caractères peuvent se trouver entre le déclencheur d'événement (onload par exemple) et le javascript :
    • !#$%&()*~+-_.,:;?@[/|\]^`

Ce ne sont pas des balises ni des séparateurs. Ce sont des noms d'attributs ou bien des couples “nom/valeur” qui permettent l'activation de comportements favorables à l'interprétation d'un script. Certains ne sont valables que dans des contextes très précis, d'autres sont beaucoup plus versatiles. Je présente les attributs proposés par l'auteur de la page web ci-dessous (avec, entre parenthèses, le contexte dans lequel l'attirbut était présenté pour l'exemple)

  • src pour toute balise, ou presque
  • style pour toute balise, ou presque (peut contenir une chaîne “xss:expression(<script à réaliser>)”
  • onload (dans une balise BODY)
  • dynsrc, lowsrc (dans une balise IMG)
  • size (dans une balise BR)
  • href (quand on fait référence à un style)
  • background (pour TABLE et TD)
  • url pour une balise META. Permet de se passer des mots script et javascript. Tout est encodé en 64 bits…
  • les attributs “background”, “style=background-image:”

En règle générale, tout ce qui permet d'introduire une source externe est potentiellement suspect. Toute reference à une image (par une balise, un attribut ou un élément de style) ou une feuille de style, etc. permet d'introduire un XSS.

L'ensemble des chaînes de caractère pré-décrites peuvent être camouflées de diverses manières pour passer les filtres. Voici certains des moyens employés à cet effet :

  • caractère nul : “\0”. Ça fait deux caractères et c'est ignoré par les navigateurs
  • commentaires : <!—-!> Un moyende scinder en deux des chaînes suspectes.
  • encodage : comme le chevron ouvrant, d'autres caractères peuvent être encodés en UTF-8, ASCII-US, etc. pour ne pas être repérés
  • espaces, tabulations, sauts de lignes : peuvent être utilisés pour splitter une chaîne de caractère suspecte.
  • les guillemets. À préciser, mais leur usage est, dans certains cas facultatifs.

Ce peut-être soit une chaîne de caractère contenant le texte du script, soit un pointeur vers la source du script, généralement un fichier ”.js“, mais ce peut être également un faux fichier image, ou un fichier ”.htc“. Ce dernier (HTML component) est un mécanimse d'internet explorer pour externaliser une parti de la page web. C'est un document HTML qui contient des scripts et des éléments propres à la syntaxe HTC. Voir http://msdn2.microsoft.com/en-us/library/ms531018.aspx .

Il existe également des formes d'introduviot de scripts qui n'ont rien à voir avec des balises (donc beaucoup plus pénibles à introduire dans une expression régulière).

Le plus pénible est l'actionscript :

a="get";
b="URL(\"";
c="javascript:";
d="alert('XSS');\")";
eval(a+b+c+d);

L'auteur de la page évoque également SSI et PHP, mais ces failles imposent de pouvoir lancer des scripts locaux à partir de l'interface. Comme il le dit (presque) lui-même : “si c'est réalisable, vous avez des problèmes autrement plus important que le XSS”.

On trouvera toujours un tordu pour contourner notre belle protection. :( Les ennemis visibles sont, a priori, les balises IMG, STYLE et SCRIPT. Ce sont les plus évidentes. On élimine certainement 90% des problèmes si on les dégage, en tenant compte des variations de présentations qu'ils peuvent avoir.

IMG pose problème parce qu'on peut en avoir besoin pour des raisons tout à fait légitimes, comme mettre une jolie image sur la page d'accueil de sa liste.

En revanche, d'autres balises moins fréquemment utilisées n'ont clairement rien à faire dans les champs de configuration de Sympa (EMBED, LINK, META,…) On pourrait dégager celles-ci sans le moindre remord.

Les endroits à filtrer

  • Les zone de saisie de texte libre (profil, liste). tout ce qui est accessible au moins aux propriétaires. On fait confiance aux listmasters, hein ?
  • Les documents partagés qui seront présentés avec un content-type=“text/plain|text/html|text-shtml FIXME
  • Les scénarios (ils sont affichés comment dans l'interface web) ?

Où faire intervenir le filtrage dans le code ?

Il existe une fonction bas niveau de contrôle des paramètres saisis.

  • dev/cross-site_scripting.1183024519.txt.gz
  • Last modified: 2007/06/28 12:19
  • (external edit)