Contrôler Flow Guard pour la sécurité de la plateforme
Qu’est-ce que Control Flow Guard ?
Le contrôle Flow Guard (CFG) est une fonctionnalité de sécurité de plateforme hautement optimisée qui a été créée pour lutter contre les vulnérabilités de corruption de la mémoire. En plaçant des restrictions strictes sur l’emplacement d’exécution du code d’une application, il est beaucoup plus difficile pour les exploits d’exécuter du code arbitraire via des vulnérabilités telles que les dépassements de mémoire tampon. CFG étend les technologies d’atténuation des exploits précédentes telles que /GS, DEP et ASLR.
- Empêcher la corruption de la mémoire et les attaques par ransomware.
- Limitez les fonctionnalités du serveur à ce qui est nécessaire à un moment donné pour réduire la surface d’attaque.
- Compliquez l’exploitation du code arbitraire par le biais de vulnérabilités telles que les dépassements de mémoire tampon.
Cette fonctionnalité est disponible dans Microsoft Visual Studio 2015 et s’exécute sur les versions « CFG-Aware » de Windows , les versions x86 et x64 pour Desktop et Server de Windows 10 et Mise à jour Windows 8.1 (KB3000850).
Nous encourageons fortement les développeurs à activer CFG pour leurs applications. Vous n’avez pas besoin d’activer CFG pour chaque partie de votre code, car un mélange de code CFG activé et non-CFG s’exécute correctement. Mais l’échec de l’activation de CFG pour tout le code peut ouvrir des lacunes dans la protection. En outre, le code compatible CFG fonctionne correctement sur les versions « CFG-Ignore » de Windows et est donc entièrement compatible avec eux.
Comment activer CFG ?
Dans la plupart des cas, il n’est pas nécessaire de modifier le code source. Tout ce que vous devez faire est d’ajouter une option à votre projet Visual Studio 2015, et le compilateur et l’éditeur de liens activeront CFG.
La méthode la plus simple consiste à accéder à Project | Propriétés | Propriétés de configuration | | C/C++ Génération de code et choisissez Oui (/guard:cf) pour Le contrôle Flow Guard.
Vous pouvez également ajouter /guard:cf à Project | Propriétés | Propriétés de configuration | | C/C++ Ligne de commande | Options supplémentaires (pour le compilateur) et /guard:cf pour Project | Propriétés | Propriétés de configuration | Éditeur de liens | Ligne de commande | Options supplémentaires (pour l’éditeur de liens).
Pour plus d’informations, consultez /guard (Activer le contrôle Flow Guard).
Si vous créez votre projet à partir de la ligne de commande, vous pouvez ajouter les mêmes options. Par exemple, si vous compilez un projet appelé test.cpp, utilisez cl /guard:cf test.cpp /link /guard:cf.
Vous avez également la possibilité de contrôler dynamiquement l’ensemble d’adresses cibles icall considérées comme valides par CFG à l’aide de SetProcessValidCallTargets à partir de l’API Gestion de la mémoire. La même API peut être utilisée pour spécifier si les pages sont des cibles non valides ou valides pour CFG. Les fonctions VirtualProtect et VirtualAlloc traitent par défaut une région spécifiée de pages exécutables et validées comme des cibles d’appels indirects valides. Il est possible de remplacer ce comportement, par exemple lors de l’implémentation d’un compilateur juste-à-temps, en spécifiant PAGE_TARGETS_INVALID lors de l’appel de VirtualAlloc ou PAGE_TARGETS_NO_UPDATE lors de l’appel de VirtualProtect comme indiqué dans les constantes de protection de la mémoire.
Comment dire qu’un binaire est sous contrôle Flow Guard ?
Exécutez l’outil dumpbin (inclus dans l’installation Visual Studio 2015) à partir de l’invite de commandes Visual Studio avec les options /headers et /loadconfig : dumpbin /headers /loadconfig test.exe. La sortie d’un fichier binaire sous CFG doit montrer que les valeurs d’en-tête incluent « Guard », et que les valeurs de configuration de charge incluent « CF Instrumented » et « TABLE FID présente ».
Comment le CFG fonctionne-t-il vraiment ?
Les vulnérabilités logicielles sont souvent exploitées en fournissant des données peu probables, inhabituelles ou extrêmes à un programme en cours d’exécution. Par exemple, un attaquant peut exploiter une vulnérabilité de dépassement de mémoire tampon en fournissant plus d’entrée à un programme que prévu, ce qui permet de sur-exécuter la zone réservée par le programme pour contenir une réponse. Cela peut endommager la mémoire adjacente qui peut contenir un pointeur de fonction. Lorsque le programme appelle par le biais de cette fonction, il peut ensuite passer à un emplacement inattendu spécifié par l’attaquant.
Toutefois, une combinaison puissante de la prise en charge de la compilation et du temps d’exécution de CFG implémente l’intégrité du flux de contrôle qui restreint étroitement l’emplacement où les instructions d’appel indirect peuvent s’exécuter.
Le compilateur effectue les opérations suivantes :
- Ajoute des vérifications de sécurité légères au code compilé.
- Identifie l’ensemble des fonctions dans l’application qui sont des cibles valides pour les appels indirects.
Prise en charge du runtime, fournie par le noyau Windows :
- Conserve efficacement l’état qui identifie les cibles d’appels indirects valides.
- Implémente la logique qui vérifie qu’une cible d’appel indirect est valide.
Pour illustrer :
Lorsqu’une vérification CFG échoue lors de l’exécution, Windows met immédiatement fin au programme, ce qui interrompt tout exploit qui tente indirectement d’appeler une adresse non valide.