JavaScript a certaines limites, telles que la lecture et l'écriture sur le disque et l'interdiction d'accès à d'autres fenêtres ou domaines de navigateur. Mais est-ce tout ce qu'il faut pour empêcher l'exécution de code malveillant?
JavaScript est assez puissant, et il semble étrange que les navigateurs exécutent sans aucun doute tout le code JavaScript qui leur est fourni. Comment est-ce sûr?
La norme est conçue pour être sûre. L'implémentation peut-être pas.
Le navigateur isole JavaScript, car il s'exécute dans un processus de navigateur lui-même. Il ne peut rien faire qui ne soit autorisé par l'interpréteur JavaScript du navigateur ou le compilateur JIT. Cependant, en raison de sa complexité, il n'est pas rare de trouver des vulnérabilités qui permettent à JavaScript de compromettre le navigateur et d'obtenir l'exécution de code arbitraire avec les privilèges du processus du navigateur.
Étant donné que ces types de bogues de sécurité sont si courants, de nombreux navigateurs implémentent un sandbox. Il s'agit d'un mécanisme de protection qui tente d'isoler un processus de navigateur compromis et de l'empêcher de causer des dommages supplémentaires. Le fonctionnement du sandbox dépend du navigateur. Firefox a un sandboxing très limité, tandis que Chrome et Edge ont un sandboxing important. Cependant, malgré cette défense en profondeur, les vulnérabilités du navigateur peuvent souvent être combinées avec des vulnérabilités d'échappement sandbox.
Comment est-ce sûr?
Ce n'est pas. Ou plus exactement, il est aussi sûr que l'implémentation du navigateur. Les navigateurs (y compris leur moteur JavaScript) sont des logiciels complexes, avec l'ajout régulier de nouvelles fonctionnalités - parce que les utilisateurs les veulent.
Cela signifie que, même si les plus connus ont certainement une procédure de qualité pour tester leur code contre des vulnérabilités connues, le risque d'une faille non détectée dans l'implémentation d'une fonctionnalité existe toujours.
Actuellement, la méthode acceptée est que dès qu'une violation est détectée, une nouvelle version contenant un correctif est publiée. Mais entre la découverte de la faille et l'installation du correctif, le navigateur est vulnérable, c'est pourquoi il est recommandé de maintenir son navigateur à jour, afin de ne s'exposer qu'à zero-day vulnérabilités.
Il est vrai qu'au niveau JavaScript, les navigateurs sont conçus pour sandboxer le code en cours d'exécution (principalement en n'exposant aucune API dangereuse), mais JavaScript est un langage très complexe à analyser et exécuter.
ECMAScript est la norme derrière JavaScript, en raison de l'énorme inflation marketing autour des langages de programmation adaptés aux débutants que nous connaissons aujourd'hui, ECMAScript se met à jour rapidement et introduit des fonctionnalités de plus en plus complexes à implémenter pour un runtime.
Ceci, à son tour, élargit la surface d'attaque et permet aux bogues de s'introduire.
Un exemple merveilleux est le travail récent de Patrick Biernat , Markus Gaasedelen , Amy Burnett pour le pwn2own 2018.
http://blog.ret2.io/2018/06/05/pwn2own-2018-exploit-development/
Le blog décrit la découverte d'un 0day qui permet l'exécution de code arbitraire dans WebKit et comment cela est utilisé pour exploiter un autre 0day dans le gestionnaire de fenêtres macOS pour échapper au sanbox Safari en cours d'exécution (c'est un sandbox macOS , pas celui de Safari) pour passer à "root" et posséder le système.
Bref, en visitant simplement un lien tout en activant JavaScript, un système macOS peut être totalement compromis sans un seul problème visible pour l'utilisateur.
Voilà à quel point JavaScript peut être sûr: Aussi sûr qu'un logiciel complexe que le JSCore de WebKit peut l'être.
C'est pourquoi il est conseillé aux utilisateurs qui nécessitent une sécurité élevée de désactiver JavaScript (c'est une exigence assez courante dans le DarkWeb, par exemple).
La vulnérabilité dans WebKit découverte par les auteurs ci-dessus est une condition de concurrence entre le garbage collector nouvellement introduit et le array.reverse
fonction: si le GC commence à marquer un tableau alors qu'il est inversé, cela pourrait conduire à un exploit UAF (Use After Free). La marque se fait séquentiellement sur le tableau, supposons que le GC se trouve juste au milieu du tableau lorsque celui-ci est inversé, puis la seconde moitié n'est jamais marquée et donc élue pour la collection, ce qui entraîne un UAF (l'objet du tableau lui-même n'est pas collecté, seul son élément).
Comment un UAF est utilisé pour créer des primitives d'exploitation plus puissantes pouvant conduire à l'exécution de code arbitraire est plus ou moins une variation des mêmes techniques: d'abord un objet intéressant est alloué dans l'espace nouvellement libéré (par exemple un tableau) puis une primitive RW est créés (par exemple en modifiant la limite du tableau) et enfin des opcodes arbitraires sont écrits en mémoire (par exemple dans une page JITted).
Les détails de cette journée particulière se trouvent dans le blog lié.
La partie intéressante est la façon dont ce 0day a été trouvé: étant donné que WebKit est si grand, un examen approfondi du code est impossible sans un énorme effort et une gigue automatisée a été mise en place.
Cela doit nous faire réfléchir sur le fait que lorsque nous avons des centaines de milliers ou des millions de lignes de code, il est très difficile de faire en sorte que chacune se comporte bien par rapport à toutes les autres.
Comme indiqué dans d'autres réponses, chaque navigateur possède son propre moteur de script conçu pour exécuter sandbox en JavaScript et chaque moteur tente de limiter la fonctionnalité JavaScript pouvant entraîner un comportement malveillant.
Mais en règle générale, JavaScript n'a jamais été sécurisé dans le navigateur. Les développeurs de codes malveillants trouvent constamment des moyens d'exploiter le fonctionnement de chaque moteur ainsi que ses fonctionnalités JavaScript disponibles pour atteindre des objectifs malveillants.
Au cours des premières années, JavaScript était plutôt dangereux dans le navigateur. Maintenant, c'est une course constante entre les développeurs de code malveillant et les développeurs de navigateur/moteur et, finalement, les développeurs malveillants gagnent toujours, même si ce n'est que pour une courte période. Ainsi, JavaScript peut difficilement être qualifié de sûr. "Devrait être en sécurité pour l'instant" est une façon plus précise de le dire.
JavaScript est assez puissant
C'est pourquoi de nombreux utilisateurs le considèrent dangereux et le bloquent à l'aide d'extensions de navigateur. JavaScript permet aux sites Web de suivre les utilisateurs de manières impossibles sans cela, y compris l'identification des utilisateurs après avoir supprimé leurs cookies en prenant les empreintes digitales du navigateur. De nombreuses API Web plus récentes, telles que WebUSB, autorisent des éléments qui ne sont pas du tout sûrs, mais les navigateurs demanderont la permission de l'utilisateur lors de l'accès à des API dangereuses comme USB et l'appareil photo.
Il n'y a rien de intrinsèquement sûr à propos de JavaScript, à bien des égards, il est moins sûr que d'autres langages:
C'est le bac à sable où le navigateur exécute le JavaScript qui assure la sécurité. Voir la documentation sur le Chrome sandbox ici , notez qu'il n'y a aucune référence à JavaScript ou au script ECMA.
Aujourd'hui, la grande majorité du code exécuté dans le navigateur est écrit en JavaScript. Avec la montée en puissance de WebAssembly , nous verrons probablement la plate-forme de navigateur passer du verrouillage principalement à une seule langue d'aujourd'hui (comme un mainframe du passé) à une plate-forme ouverte où n'importe quelle langue compatible WebAssembly peut être utilisée. . Cela prouvera en quelque sorte que JavaScript n'est pas particulièrement sûr/spécial, car à ce stade, de nombreuses langues s'exécuteront dans le navigateur. Toutes ces langues utiliseront le sandbox fourni par le navigateur pour s'exécuter.
JavaScript est "relativement sûr", mais pas "absolument sûr". Tout code que vous exécutez sur votre système a le potentiel de nuire. Il n'y a pas de système parfaitement sûr, sauf celui qui n'a jamais été utilisé. JavaScript est plus sûr que de placer un périphérique USB inconnu dans votre ordinateur et plus sûr qu'un binaire que vous téléchargez à partir d'un site Web louche ou que vous obtenez dans une pièce jointe suspecte, et beaucoup plus sûr que certains des scripts que vous trouverez sur les sites Web qui vous disent de copiez-collez-les dans votre Shell.
Il a des fonctionnalités de sécurité: un bac à sable pour aider à isoler le processus, une API relativement limitée qui a des contraintes de sécurité pour éviter d'exécuter des instructions informatiques arbitraires, et des contrôles de sécurité destinés à limiter l'exposition des données sensibles comme les empreintes digitales ou le partage de données entre domaines. Ce sont au-dessus des contrôles de votre système d'exploitation appliqués au binaire du navigateur pour limiter les mauvais comportements et des applications antivirus qui peuvent aider à stopper de telles attaques.
Cependant, ce n'est pas absolument sûr. Les bogues dans le moteur d'exécution du navigateur, le navigateur lui-même, l'antivirus ou même le processeur lui-même peuvent tous compromettre la sécurité de JavaScript. Le système n'est aussi sûr que sa sécurité la plus faible. La sécurité de JavaScript est principalement destinée à empêcher les exploits "occasionnels" (comme un JavaScript de 8 ans qui apprend pour la première fois et écrit accidentellement un exploit), mais n'a aucune chance contre les attaquants dédiés. JavaScript est suffisamment compliqué pour qu'il y ait forcément des bogues, peut-être de manière étrange et inattendue.
Ceux qui sont expérimentés dans le piratage, les tests de plumes et la sécurité peuvent parcourir le code source, déboguer les exécutables et faire tout ce qu'ils peuvent pour essayer de trouver des failles dans l'armure. Les points faibles de l'implémentation JavaScript. Et JavaScript est suffisamment grand pour que de telles lacunes existent pour commencer, car il est pratiquement impossible d'automatiser même tous les tests possibles qui trouveraient ces bogues.
De manière générale, tout script typique que vous pourriez rencontrer sur un site Web typique est probablement "sûr", en particulier ceux liés aux principaux moteurs de recherche. Cependant, une fois que vous commencez à sortir des sentiers battus, il est incroyablement probable que votre système soit compromis à un moment donné s'il n'y a même qu'un seul point faible. Il suffit d'un très bon exploit, ou parfois deux ou trois en tandem, pour reprendre complètement un système.
En l'état, n'activez JavaScript que pour les sites en lesquels vous avez confiance (j'utilise personnellement NoScript à cette fin), gardez toujours tous vos logiciels à jour et faites toujours attention aux avertissements du navigateur tels que les certificats invalides, etc. Même alors, vous ne serez pas sûr à 100%, mais vous prendrez une part active à votre propre stratégie d'atténuation.
Il est sûr par rapport au code exécutable au niveau de la machine, comme les utilisations ActiveX.
Un programme de code machine a un accès absolu à toutes les interfaces que le système d'exploitation et les bibliothèques fournissent à tout programme fonctionnant sous ce compte d'utilisateur, il est VRAIMENT limité dans ce qu'il peut faire par ce que le matériel et le système d'exploitation lui limitent - essentiellement faire un tel programme aussi puissant que l'utilisateur qui l'exécute. Il peut y avoir des outils qui tentent de le restreindre en interceptant certaines des interfaces fournies, mais il est difficile d'arrêter un programme conscient de telles mesures pour les contourner.
L'interpréteur javascript fait partie du navigateur et est écrit de manière à n'offrir au programme qu'il exécute que les interfaces et les pouvoirs qu'il souhaite leur offrir.
Cette réponse portera sur deux points soulevés à la question et une "fonctionnalité" de navigateur non soulevée dans la question.
JavaScript a certaines limites telles que la lecture et l'écriture sur le disque
une telle limitation n'existe pas techniquement sur les navigateurs Chromium/Chrome où requestFileSystem
est défini, qui écrit directement sur le disque; C'est le File System
dossier du répertoire de configuration Chromium/Chrome dans le système de fichiers des utilisateurs.
Voir Comment écrire dans un fichier (répertoire utilisateur) en utilisant JavaScript?
et ne pas autoriser l'accès à d'autres fenêtres ou domaines de navigateur.
Si un window
est ouvert à partir d'un window
déjà ouvert, la communication entre window
s est possible en utilisant, mais sans s'y limiter, postMessage
, MessageChannel
, SharedWorker
, ou simplement interroger les paramètres de chaîne.
Voir Comment puis-je charger un travailleur Web partagé avec un script utilisateur?
Un autre point non mentionné à l'OP qui doit être soulevé ici spécifique à Chromium/Chrome est le fait que l'implémentation SpeechRecognition
de l'API Web Speech sur ces navigateurs enregistre la voix des utilisateurs (identifiant biométrique) et envoie cet enregistrement à un service à distance, sans informer directement l'utilisateur de ce qui se passe. Il n'est pas immédiatement clair si les enregistrements sont conservés (pour toujours) par le "service Web" non divulgué ou "supprimés" à un moment donné.
Voir WebkitSpeechRecognition envoie-t-il l'audio enregistré à un service Web distant par défaut?