Explorez le fonctionnement des mécanismes de portabilité et de sécurité de WebAssembly (WASM) grâce à ce guide introductif.
Ces deux aspects représentent des concepts avancés de WebAssembly (WASM). Il est conseillé de prendre connaissance des deux articles précédents de notre série « WebAssembly pour débutants » avant de continuer.
Entamons notre exploration.
La Portabilité de WebAssembly
La portabilité est l’un des atouts majeurs de WebAssembly, le rendant idéal pour le web. On peut considérer WASM comme une plateforme portable et sécurisée dans un environnement isolé.
De plus, son format binaire permet une exécution sur diverses architectures de processeurs et systèmes d’exploitation. Cela signifie que l’utilisation de WASM ne se limite pas au web, mais s’étend à d’autres contextes.
Pour appréhender la portabilité de WASM, nous examinerons les points suivants :
- L’environnement d’exécution : local, limité et non déterministe.
- Les spécificités de l’environnement d’exécution.
- La portabilité de WASM pour le web et au-delà.
Environnement Local, Limité et Non Déterministe
WASM nécessite des environnements d’exécution efficaces, caractérisés comme locaux, limités et non déterministes. Le non-déterminisme signifie qu’un même algorithme, compilateur ou environnement peut produire différents résultats pour une même entrée. C’est l’opposé d’un algorithme déterministe.
Les notions d’environnement « limité » et « local » sont étroitement liées au comportement non déterministe. Pour que le non-déterminisme fonctionne correctement, il faut des cas d’utilisation bien définis et « limités ».
De plus, ces exécutions sont « locales » et n’ont pas d’impact à l’extérieur de l’environnement. Pour une analyse approfondie du non-déterminisme, consultez la documentation officielle de WebAssembly.
Particularités de l’Environnement d’Exécution
Pour assurer la portabilité de WebAssembly, son environnement d’exécution doit respecter les critères suivants :
- Gestion de la mémoire au niveau de l’octet, avec des octets de 8 bits.
- Utilisation d’entiers signés de 32 bits en complément à deux, avec une option pour les 64 bits.
- Émulation logicielle possible via des accès mémoire non alignés ou des pièges fiables.
- Support des nombres à virgule flottante de 32 et 64 bits selon la norme IEEE 754-2008.
- Garantie de progression pour tous les threads d’exécution.
- Pour les accès 64 bits, wasm64 doit proposer des opérateurs de mémoire atomiques sans verrouillage.
- Les opérateurs de mémoire atomique sans verrouillage incluent des accès de 8, 16 et 32 bits.
- wasm64 gère la mémoire linéaire au-delà de 4 Go avec des index ou des pointeurs de 64 bits.
- Ordre des octets en little-endian.
Tous les navigateurs majeurs, comme Chrome, Edge, Firefox et WebKit, respectent ces exigences.
De plus, WebAssembly évolue rapidement. Le groupe communautaire WASM et le groupe de travail W3C WebAssembly œuvrent à sa standardisation. Cela implique que ces exigences sont susceptibles d’évoluer à l’avenir.
Portabilité de WASM pour le Web et Au-delà
L’objectif principal de WebAssembly est d’offrir une portabilité et des performances proches du natif, aussi bien sur le web qu’en dehors. Nous allons voir comment WASM atteint cet objectif.
#1. Intégration Web
WASM s’intègre de manière fluide dans l’écosystème web, en respectant le modèle de sécurité web, la portabilité web et les API web. De plus, il doit laisser suffisamment de place pour un développement créatif ultérieur (pour mieux cerner ses objectifs, lisez la deuxième partie de « WebAssembly pour débutants »).
Comment WASM assure-t-il sa compatibilité avec le web ? Il s’appuie sur les API JavaScript, permettant aux développeurs d’utiliser aisément JavaScript pour la compilation de modules WebAssembly. Il prend également en charge le stockage et la récupération des modules compilés, la gestion des importations et de la mémoire, etc.
Pour en savoir davantage sur la manière dont WASM atteint une telle compatibilité web, consultez cet article : Intégration Web – WebAssembly.
#2. Intégration Non-Web
Comme mentionné précédemment, WASM fonctionne également dans des environnements non web. En tant que développeur ou entreprise, vous pouvez créer des applications performantes ou écrire certaines sections de votre application qui nécessitent une optimisation des performances. Il peut être utilisé, par exemple, sur des appareils IoT, des serveurs de centres de données ou des applications de bureau/mobiles.
Comme les applications non web ne peuvent pas utiliser les API web, elles reposent sur la liaison dynamique de WASM. Il est également nécessaire de recourir aux tests de fonctionnalités, une pratique de développement qui teste différentes variantes des fonctionnalités pour déterminer la meilleure expérience utilisateur. De plus, les développeurs peuvent utiliser des machines virtuelles JavaScript pour simplifier l’intégration non web, ou développer leurs applications sans.
Pour plus d’informations, consultez cet article : Intégrations Non-Web – WebAssembly.
La Sécurité de WebAssembly
WebAssembly est une solution au format binaire offrant des performances proches du natif. Il excelle sur le web, mais peut également être adapté à des intégrations non web. Cette polyvalence augmente la portée de WASM, mais également les problèmes de sécurité.
Les Défis et Risques de Sécurité de WASM
Bien que WebAssembly soit considéré comme sûr et efficace, il n’est pas exempt de risques de sécurité, notamment :
- Le bac à sable WebAssembly
- La gestion de la mémoire
- L’obfuscation du code
- Les contrôles d’intégrité
#1. Le Bac à Sable WebAssembly
WASM s’exécute dans le navigateur web, comme JavaScript. Il utilise la même machine virtuelle (VM) que JavaScript. Le bac à sable fournit un environnement d’exécution sécurisé, limitant les interactions.
Toutefois, si un code JavaScript/WebAssembly contient du code malveillant, il peut être difficile à détecter car il est exécuté dans une « boîte noire ». De plus, le code WASM est au format binaire, ce qui le rend plus rapide à exécuter et plus difficile à analyser par les antivirus. Le code peut par exemple contenir des publicités indésirables ou rediriger les utilisateurs vers des sites malveillants.
De plus, la dépendance excessive de WebAssembly à l’égard de JavaScript pour son exécution sur le web signifie qu’il hérite des vulnérabilités de JavaScript. Il est donc essentiel pour les développeurs de respecter les précautions et mesures de sécurité de JavaScript lors du codage en WASM.
#2. La Gestion de la Mémoire
La gestion de la mémoire dans WASM est complexe. Premièrement, il n’accède pas directement à la mémoire physique car il s’exécute dans la VM. Il utilise la mémoire de la machine hôte.
Deuxièmement, le nettoyage de la mémoire dans WASM nécessite un processus explicite, contrairement à JavaScript qui se nettoie automatiquement.
De plus, lorsqu’une fonction WASM renvoie une sortie à JavaScript, elle renvoie un pointeur vers la position dans l’espace mémoire alloué. Si la mémoire allouée est pleine, le programme WASM peut planter, nuisant à l’expérience utilisateur. Pour éviter cela, les programmeurs doivent utiliser des outils de désinfection pour déboguer leur code ou utiliser des outils comme emscripten.
#3. L’Obfuscation du Code
L’exécution en bac à sable de WASM rend son code obscur. De plus, le format binaire de WASM n’est pas lisible par l’homme, ce qui complique l’analyse rétro-ingénierie, pourtant nécessaire pour détecter du code malveillant.
Ces caractéristiques rendent le débogage du code WebAssembly difficile en raison de son absence de format lisible par l’homme. Cela crée des failles de sécurité, permettant par exemple aux pirates de cacher du code qui vole des informations sensibles ou qui prend le contrôle de la machine hôte.
#4. Les Contrôles d’Intégrité
Toute donnée transférée via le web est vulnérable à la falsification. Par exemple, des pirates peuvent réaliser une attaque « man-in-the-middle » pour modifier les valeurs des données. C’est un problème pour WASM car il n’a pas de moyen intégré d’effectuer des contrôles d’intégrité.
Il peut toutefois collaborer avec JavaScript pour effectuer ces contrôles. On peut également utiliser des outils d’intégration comme Jit pour identifier les vulnérabilités potentielles du code WASM. Cela assure que le code est exempt de tout acteur malveillant et ne nuit ni aux applications, ni à l’infrastructure cloud.
Comprendre le Modèle de Sécurité WASM
WebAssembly accorde une grande importance à la sécurité. Sa documentation officielle précise que son modèle de sécurité poursuit deux objectifs principaux :
Le modèle de sécurité WASM reconnaît que les applications WebAssembly s’exécutent de manière autonome, sans pouvoir échapper à l’environnement sandbox. Cependant, les API peuvent être une porte d’entrée pour attaquer l’environnement hôte.
Une autre technique de tolérance aux pannes consiste à exécuter les applications de manière déterministe avec des attentes limitées. En assurant ces deux conditions, la majorité des exécutions d’applications sont considérées comme sûres.
Pour renforcer la sécurité, les développeurs doivent appliquer la politique d’origine identique pour le flux d’informations. Si vous développez des applications non web, il convient d’utiliser le modèle de sécurité POSIX. Pour plus d’informations sur le modèle de sécurité, consultez cet article : Sécurité – WebAssembly.
L’Interface Système WebAssembly (WASI)
WASI (The WebAssembly System Interface) joue également un rôle clé dans l’intégration non web de WASM, en renforçant la sécurité. Il s’agit d’une interface système modulaire qui offre des fonctionnalités de sécurité et de portabilité intéressantes.
WASI fait désormais partie de la charte du sous-groupe d’interface système WebAssembly et est en cours de normalisation. Grâce à WASI, WASM est largement adopté dans différents domaines de l’informatique edge/server. De plus, WASI simplifie la sécurité lors de la transition d’une intégration web vers une intégration non web.
En conclusion
La portabilité et la sécurité de WebAssembly sont des sujets vastes. Dans cette troisième partie de « WebAssembly pour débutants », nous avons tenté de les simplifier et de les décomposer, en particulier pour les novices.
Pour aller plus loin, vous pouvez consulter les pense-bêtes JavaScript pour développeurs et apprenants.