- On ne peut prétendre remplir tout l’espace mémoire disponible, les chances de tomber
sur de la mémoire sous contrôle restent donc limitées.
- Compromis chances de réussite / Mémoire consommée.
- Consommation excessive de mémoire signifie perte de performances, ce qui peut
alerter la victime.
Vers un contrôle affiné de l’état de la mémoire
La méthode présentée par Alexander Sotirov à la black hat 2007 (à Amsterdam) propose de
tirer un trait sur ces limitations en affinant le contrôle de l’état de la mémoire, rendant donc
inutile ce remplissage excessif. Il propose d’utiliser les mécanismes internes du moteur
JavaScript de Internet Explorer pour prédire et contrôler l’état de la mémoire.
Le concept est le suivant :
<script language=’javascript’>
Var str1=’AAAAAAAAAAAAAAAAA’ ; // n’alloue pas de mémoire
Var str2 = str1.substr(0, 10) ; // alloue une chaîne de 10
caractères
</script>
Un des fondements de ce schéma d'attaque repose sur le fait que JavaScript, qui utilise
(normalement) une heap séparée, va en fait utiliser la heap de Internet Explorer lorsqu'il s'agit
d'allouer des chaînes de caractères.
En analysant plus profondément l’implémentation du moteur javascript on se rend compte
qu’il est même possible d’implémenter un équivalent des routines d’allocation et de libération
de mémoire en javascript. Ce qui veut dire qu’au lieu d’envahir la mémoire pour maximiser
nos chances, il est possible de prévoir très précisément ou nôtre bloc sera alloué.
En tenant compte du mode de fonctionnement du moteur JavaScript et d’un certain nombre de
facteurs comme :
- Le garbage collector de JavaScript
- Les problématiques de fragmentation dans le cadre de l’exploitation de heap overflow
- Les différentes listes maintenues par l’allocateur (lookaside buffers)
Alexander Sotirov en arrive à présenter une API tout à fait similaire à celle du système lui-
même, ce qui facilite considérablement la tâche. C’est un peu comme si l’attaquant pouvait
participer de manière intrusive au déroulement du programme.
Ce niveau de contrôle de l'état de la heap au travers d'un langage de si haut niveau est possible
car l'algorithme de l'allocateur est tel qu'il est facilement possible de créer une routine qui va
défragmenter la heap (donc remplir tous les trous qui auraient pu être crées au cours de
l'exécution du programme au travers de diverses allocations/libérations de mémoire), et de
mettre les listes internes maintenues par l'allocateur dans un état tel que l'on s'assure que
chaque nouvel appel à l'allocateur allouera de la mémoire 'fraîche' (on entend par la qu'il n'ira
pas chercher des blocs déjà utilises et libérés).
<script language=’javascript’>
Heap.alloc(0x2000) ;
Heap.alloc(0x2020, ‘to_be_freed’);
Heap.alloc(0x2020);
Heap.free(‘to_be_freed’);
</script>