Les extensions ont accès à des privilèges spéciaux dans le navigateur, ce qui en fait une cible attrayante pour les pirates informatiques. Si une extension est compromise, chaque utilisateur de cette extension devient vulnérable à des intrusions malveillantes et indésirables. Intégrez ces pratiques pour sécuriser une extension et protéger ses utilisateurs.
Protéger les comptes de développeur
Le code de l'extension est importé et mis à jour via les comptes Google. Si les comptes des développeurs sont compromis, un pirate informatique pourrait envoyer du code malveillant directement à tous les utilisateurs. Pour les protéger, activez l'authentification à deux facteurs, de préférence avec une clé de sécurité.
Faites en sorte que les groupes soient sélectifs.
Si vous utilisez la publication par groupe, limitez le groupe aux développeurs de confiance. N'acceptez pas les demandes d'adhésion provenant de personnes inconnues.
Ne jamais utiliser HTTP
Lorsque vous demandez ou envoyez des données, évitez d'établir une connexion HTTP. Supposons que les connexions HTTP soient interceptées par des écoutes clandestines ou contiennent des modifications. Veillez à toujours privilégier le protocole HTTPS, car sa sécurité intégrée permet de contourner la plupart des attaques MITM ("man in the middle").
Demander des autorisations minimales
Le navigateur Chrome limite l'accès d'une extension aux droits qui ont été explicitement demandés dans le fichier manifeste. Les extensions doivent réduire leurs autorisations en n'enregistrant que les API et les sites Web dont elles dépendent.
Limiter les privilèges d'une extension limite ce qu'un pirate informatique peut exploiter.
Récupération multi-origine()
Une extension ne peut utiliser que fetch()
et XMLHttpRequest()
pour obtenir des ressources de l'extension et des domaines spécifiés dans les autorisations. Notez que les appels vers ces deux services sont interceptés par le gestionnaire fetch du service worker.
{
"name": "Very Secure Extension",
"version": "1.0",
"description": "Example of a Secure Extension",
"host_permissions": [
"https://developer.chrome.com/*",
"https://*.google.com/*"
],
"manifest_version": 3
}
Cette extension de l'exemple ci-dessus demande l'accès à tout le site developer.chrome.com et aux sous-domaines de Google en indiquant "https://developer.chrome.com/*"
et "https://*.google.com/*"
dans les autorisations. Si l'extension était compromise, elle ne serait autorisée à interagir qu'avec les sites Web répondant au modèle de correspondance. Le pirate informatique n'aurait qu'une capacité limitée à accéder à "https://user_bank_info.com"
ou à interagir avec "https://malicious_website.com"
.
Limiter les champs du fichier manifeste
L'inclusion de clés et d'autorisations inutiles dans le fichier manifeste crée des failles et rend une extension plus visible. Limitez les champs du fichier manifeste à ceux sur lesquels repose l'extension.
Connexion externe
Utilisez le champ "externally_connectable"
pour déclarer les extensions et pages Web externes avec lesquelles l'extension échangera des informations. Limitez les utilisateurs avec lesquels l'extension peut se connecter en externe aux sources de confiance.
{
"name": "Super Safe Extension",
"externally_connectable": {
"ids": [
"iamafriendlyextensionhereisdatas"
],
"matches": [
"https://developer.chrome.com/*",
"https://*.google.com/*"
],
"accepts_tls_channel_id": false
},
...
}
Ressources accessibles sur le Web
Lorsque les ressources sont accessibles sur le Web, sous "web_accessible_resources"
, une extension peut être détectée par les sites Web et les pirates informatiques.
{
...
"web_accessible_resources": [
{
"resources": [ "test1.png", "test2.png" ],
"matches": [ "https://web-accessible-resources-1.glitch.me/*" ]
}
]
...
}
Plus il y a de ressources Web accessibles, plus un pirate informatique peut exploiter de nouvelles possibilités. Limitez ces fichiers au minimum.
Inclure une règle de sécurité du contenu explicite
Incluez une règle de sécurité du contenu pour l'extension dans le fichier manifeste afin d'empêcher les attaques par script intersites. Si l'extension ne charge que les ressources à partir d'elle-même, enregistrez les éléments suivants:
{
"name": "Very Secure Extension",
"version": "1.0",
"description": "Example of a Secure Extension",
"content_security_policy": {
"extension_pages": "default-src 'self'"
},
"manifest_version": 3
}
Si l'extension doit utiliser l'assembly Web ou augmenter les restrictions sur les pages en bac à sable, vous pouvez les ajouter:
{
"name": "Very Secure Extension",
"version": "1.0",
"description": "Example of a Secure Extension",
"content_security_policy": {
"extension_pages": "script-src 'self' 'wasm-unsafe-eval'; object-src 'self';",
"sandboxed_pages":"script-src 'self' 'wasm-unsafe-eval'; object-src 'self';"
},
"manifest_version": 3
}
Évitez document.write() et innerHTML.
Bien qu'il puisse être plus simple de créer dynamiquement des éléments HTML avec document.write()
et innerHTML
, cela laisse l'extension et les pages Web dont dépend l'extension, ouvertes aux pirates informatiques insérant des scripts malveillants. À la place, créez manuellement des nœuds DOM et utilisez innerText
pour insérer du contenu dynamique.
function constructDOM() {
let newTitle = document.createElement('h1');
newTitle.innerText = host;
document.appendChild(newTitle);
}
Utiliser les scripts de contenu avec précaution
Si les scripts de contenu se trouvent dans un monde isolé, ils ne sont pas à l'abri des attaques:
- Les scripts de contenu sont la seule partie d'une extension qui interagit directement avec la page Web. C'est pourquoi les pages Web hostiles peuvent manipuler des parties du DOM dont le script de contenu dépend, ou exploiter un comportement inhabituel standard sur le Web, comme les éléments nommés.
- Pour interagir avec le DOM des pages Web, les scripts de contenu doivent s'exécuter dans le même processus de moteur de rendu que la page Web. Les scripts de contenu sont ainsi vulnérables aux fuites de données via des attaques par canal secondaire (par exemple, Spectre) et d'être pris par un pirate informatique si une page Web malveillante compromet le processus du moteur de rendu.
Les opérations impliquant des données sensibles (telles que les informations privées d'un utilisateur) ou des API Chrome ayant accès aux fonctions du navigateur doivent être effectuées dans le service worker des extensions. Évitez d'exposer accidentellement des droits d'extension à des scripts de contenu:
- Supposons que des messages provenant d'un script de contenu aient été rédigés par un pirate informatique (par exemple, validez et nettoyez toutes les entrées et protégez vos scripts contre les scripts intersites).
- Supposons que des données envoyées au script de contenu puissent être transmises à la page Web. N'envoyez pas de données sensibles (par exemple, les secrets de l'extension, les données d'autres origines Web, l'historique de navigation) aux scripts de contenu.
- Limitez le champ d'application des actions privilégiées pouvant être déclenchées par des scripts de contenu. N'autorisez pas les scripts de contenu à déclencher des requêtes vers des URL arbitraires ni à transmettre des arguments arbitraires aux API d'extension (par exemple, n'autorisez pas la transmission d'URL arbitraires aux méthodes
fetch()
ouchrome.tabs.create()
).
Enregistrer et nettoyer les entrées
Protégez une extension contre les scripts malveillants en limitant les écouteurs à ce qu'elle attend, en validant les expéditeurs de données entrantes et en nettoyant toutes les entrées.
Une extension ne doit s'enregistrer pour runtime.onMessageExternal
que si elle attend une communication d'une extension ou d'un site Web externe. Vérifiez toujours que l'expéditeur correspond à une source fiable.
// The ID of an external extension
const kFriendlyExtensionId = "iamafriendlyextensionhereisdatas";
chrome.runtime.onMessageExternal.addListener(
function(request, sender, sendResponse) {
if (sender.id === kFriendlyExtensionId)
doSomething();
});
Même les messages via l'événement runtime.onMessage depuis l'extension elle-même doivent être examinés pour vous assurer que MessageSender ne provient pas d'un script de contenu compromis.
chrome.runtime.onMessage.addListener(function(request, sender, sendResponse) {
if (request.allowedAction)
console.log("This is an allowed action.");
});