• Aucun résultat trouvé

Intégration du moniteur d’exécution dans un programme

3.4 Automates de sécurité

3.4.3 Intégration du moniteur d’exécution dans un programme

Un moniteur d’exécution tel que décrit par Schneider constitue un mécanisme qui s’exé- cute en parallèle aux programmes contrôlés et qui peut intervenir afin d’empêcher toute ten- tative de violation de la politique de sécurité qu’il est supposé appliquer. Cependant, les besoins en sécurité diffèrent d’un programme à un autre. De ce fait, l’approche qui se base sur un moniteur d’exécution centralisé s’occupant de l’application de toutes les politiques de sécurité s’avère très contraignante. En effet, une des difficultés de cette approche est la mise à jour des politiques de sécurité dans un contexte de chargement dynamique de pro- grammes. De plus, un moniteur commun ne peut pas tirer profit des spécificités intrinsèques de chaque programme, afin d’optimiser les vérifications de sécurité. En effet, l’optimisation d’un mécanisme de sécurité est très importante pour la viabilité de n’importe quelle solution de sécurité.

Une alternative qui permet de remédier à ces contraintes consiste à embarquer le moniteur au sein du programme à contrôler. Cette approche est connue dans la littérature sous l’appel- lation “Inlined exécution monitoring” ou “monitorage d’exécution embarqué”. Dans cette approche, un moniteur générique qui applique une politique de sécurité est embarqué au sein d’un programme et optimisé en fonction de la structure interne de ce dernier. L’avènement des automates de sécurité a influencé l’intégration des moniteurs d’exécution en explorant l’injection d’un automate de sécurité au sein du code source ou du code exécutable des pro- grammes contrôlés. Deux principaux travaux ont caractérisé cette approche d’application de la sécurité : il s’agit de Naccio[38] et SASI [37].

SASI

Dans [37], le programme à contrôler est réécrit de façon à introduire le code nécessaire à l’application d’une certaine politique de sécurité. Du nouveau code est rajouté immédia- tement avant chaque instruction correspondant à une action critique. Le code rajouté simule l’automate de sécurité spécifiant la politique de sécurité à appliquer. Dans la nouvelle version du programme, on retrouve de nouvelles variables qui ne sont accessibles que par le code de sécurité rajouté par SASI. Ces variables représentent l’état courant de l’automate de sécurité alors que le nouveau code simule la fonction de transition de l’automate de sécurité. Aussi, le code rajouté garantit que l’exécution du programme sera arrêtée, à chaque fois que l’automate détecte une tentative de violation de la politique de sécurité à appliquer.

Il est important de mentionner que pour assurer le succès de cette approche, le code ra- jouté doit être incorruptible par le code du programme d’origine. En d’autres termes, le code du programme original doit être incapable d’entraver le bon fonctionnement du moniteur dans l’application de la politique de sécurité. À vrai dire, la simulation de l’automate que l’on rajoute est équivalente à l’insertion d’un moniteur d’exécution. Cependant, il n’est pas nécessaire d’insérer le code du moniteur avant chaque instruction, vu que ce n’est pas toutes les instructions qui sont critiques à la politique de sécurité. Par conséquent, le code obtenu est sujet à des optimisations. Ces optimisations sont obtenues par l’évaluation partielle des pré- dicats tout en supprimant les tests inutiles. Le procédé d’intégration du moniteur d’exécution dans un code implique quatre étapes :

– Insertion d’une copie de l’automate de sécurité avant chaque instruction ;

– Évaluation de tous les prédicats de transitions donnés par les instructions qui suivent chaque copie de l’automate ;

– Traduction des automates de sécurité restants vers du code, qui est rajouté aux mêmes emplacements. Ce code simule des opérations de l’automate de sécurité. L’action Arrêt est invoquée par le code rajouté si l’automate doit rejeter son entrée.

Par ailleurs, SASI a été implémenté pour deux langages : l’assembleur x86 et le bytecode de la machine virtuelle Java (JVM).

Naccio

Dans [38], une architecture système est proposée afin de permettre la spécification d’une large classe de politiques de sécurité. Ces politiques de sécurité sont suffisamment génériques pour être indépendantes des plateformes système utilisées. Elles sont définies en termes de manipulations abstraites des ressources. Afin de permettre une meilleure adoption de cette approche, une bibliothèque de politiques de sécurité prédéfinies a été mise à la disposition des utilisateurs de l’architecture. De plus, des mécanismes ont été proposés afin d’appli- quer efficacement les politiques de sécurité. Ces mécanismes sont basés sur la réécriture de programmes. Cependant, au lieu d’insérer du code de sécurité au sein du code source des programmes, une alternative intéressante a été adoptée. Cette alternative consiste à centrali- ser les vérifications de sécurité au niveau des librairies. Des mécanismes de sécurité ont été développés pour l’application des politiques de sécurité sur la machine virtuelle Java ainsi que pour des exécutables Win32.

Afin de permettre la génération automatique des politiques de sécurité à partir des spéci- fications abstraites (de haut niveau), l’utilisateur doit spécifier quatre types d’informations :

– Une description abstraite des ressources système qui doivent être protégées.

– Une description détaillée des contraintes à respecter lors de la manipulation des res- sources système protégées.

– Une description des interfaces utilisées par la plateforme pour appeler les fonctions système manipulant les ressources qu’on veut protéger.

– Une description des librairies (telles que : API Java ou DLLs Win32) utilisées pour la manipulation directe des ressources à protéger.

À partir de ces informations, le générateur de politiques de sécurité génère une librairie d’application ; il s’agit d’une nouvelle version de la librairie des mécanismes de sécurité im-

plémentant les vérifications de sécurité requises pour l’application des politiques de sécurité désirées. Ainsi, l’application d’une politique de sécurité à un programme donné s’effectue par la réécriture de ce dernier en remplaçant les appels aux fonctions des librairies d’origine par des appels aux fonctions des librairies des mécanismes de sécurité générées par NACCIO.

Afin d’adopter une approche plus standard et plus portable pour l’intégration des mo- niteurs de sécurité au sein des programmes, les langages de programmation orientés-aspect (AOP) [62] ont été explorés par plusieurs chercheurs. Dans cette direction de recherche, on trouve [9] et [48]. Ces contributions sont basées sur la spécification des automates de sé- curité par des expressions “pointcut”, il s’agit de constructeurs AOP permettant la sélection d’un ensemble d’instructions du programme en se basant sur des filtres syntaxiques. Heurtées par les limitations émanant des langages AOP standards, les différentes contributions ont dû proposer des extensions aux languages AOP standards permettant la sélection d’appels de fonctions sur la base de l’historique d’exécution.