38 KiB
Méthodologie de test d'intrusion des extensions de navigateur
Apprenez le piratage AWS de zéro à héros avec htARTE (Expert en équipe rouge AWS de HackTricks)!
Autres façons de soutenir HackTricks :
- Si vous souhaitez voir votre entreprise annoncée dans HackTricks ou télécharger HackTricks en PDF, consultez les PLANS D'ABONNEMENT !
- Obtenez le swag officiel PEASS & HackTricks
- Découvrez La famille PEASS, notre collection exclusive de NFT
- Rejoignez le 💬 groupe Discord ou le groupe Telegram ou suivez-nous sur Twitter 🐦 @carlospolopm.
- Partagez vos astuces de piratage en soumettant des PR aux HackTricks et HackTricks Cloud dépôts GitHub.
Informations de base
Les extensions de navigateur sont écrites en JavaScript et chargées par le navigateur en arrière-plan. Elles ont leur DOM mais peuvent interagir avec les DOM d'autres sites. Cela signifie qu'elles peuvent compromettre la confidentialité, l'intégrité et la disponibilité d'autres sites (CIA).
Composants principaux
Les mises en page des extensions sont mieux visualisées et se composent de trois composants. Examinons chaque composant en détail.
Scripts de contenu
Chaque script de contenu a un accès direct au DOM d'une seule page web et est donc exposé à une entrée potentiellement malveillante. Cependant, le script de contenu ne contient aucune autorisation autre que la capacité d'envoyer des messages au cœur de l'extension.
Cœur de l'extension
Le cœur de l'extension contient la plupart des privilèges/d'accès de l'extension, mais il ne peut interagir avec le contenu web que via XMLHttpRequest et des scripts de contenu. De plus, le cœur de l'extension n'a pas un accès direct à la machine hôte.
Binaire natif
L'extension permet un binaire natif qui peut accéder à la machine hôte avec les privilèges complets de l'utilisateur. Le binaire natif interagit avec le cœur de l'extension via l'interface de programmation d'application de plug-in Netscape standard (NPAPI) utilisée par Flash et d'autres plug-ins de navigateur.
Limites
{% hint style="danger" %} Pour obtenir les privilèges complets de l'utilisateur, un attaquant doit convaincre l'extension de transmettre une entrée malveillante du script de contenu au cœur de l'extension et du cœur de l'extension au binaire natif. {% endhint %}
Chaque composant de l'extension est séparé des autres par des limites protectrices solides. Chaque composant s'exécute dans un processus de système d'exploitation séparé. Les scripts de contenu et les cœurs d'extension s'exécutent dans des processus sandbox inaccessibles à la plupart des services du système d'exploitation.
De plus, les scripts de contenu sont séparés de leurs pages web associées en s'exécutant dans un tas JavaScript séparé. Le script de contenu et la page web ont accès au même DOM sous-jacent, mais les deux n'échangent jamais de pointeurs JavaScript, empêchant la fuite de fonctionnalités JavaScript.
manifest.json
Une extension Chrome est simplement un dossier ZIP avec une extension de fichier .crx. Le cœur de l'extension est le fichier manifest.json
à la racine du dossier, qui spécifie la mise en page, les autorisations et d'autres options de configuration.
Exemple :
{
"manifest_version": 2,
"name": "My extension",
"version": "1.0",
"permissions": [
"storage"
],
"content_scripts": [
{
"js": [
"script.js"
],
"matches": [
"https://example.com/*",
"https://www.example.com/*"
],
"exclude_matches": ["*://*/*business*"],
}
],
"background": {
"scripts": [
"background.js"
]
},
"options_ui": {
"page": "options.html"
}
}
content_scripts
Les scripts de contenu sont chargés chaque fois que l'utilisateur accède à une page correspondante, dans notre cas toute page correspondant à l'expression https://example.com/*
et ne correspondant pas à l'expression régulière *://*/*/business*
. Ils s'exécutent comme les scripts de la page elle-même et ont un accès arbitraire au Modèle d'Objet de Document (DOM) de la page.
"content_scripts": [
{
"js": [
"script.js"
],
"matches": [
"https://example.com/*",
"https://www.example.com/*"
],
"exclude_matches": ["*://*/*business*"],
}
],
Pour inclure ou exclure davantage d'URL, il est également possible d'utiliser include_globs
et exclude_globs
.
Voici un exemple de script de contenu qui ajoutera un bouton d'explication à la page lorsque l'API de stockage est utilisée pour récupérer la valeur message
du stockage de l'extension.
chrome.storage.local.get("message", result =>
{
let div = document.createElement("div");
div.innerHTML = result.message + " <button>Explain</button>";
div.querySelector("button").addEventListener("click", () =>
{
chrome.runtime.sendMessage("explain");
});
document.body.appendChild(div);
});
Un message est envoyé aux pages d'extension par le script de contenu lorsque ce bouton est cliqué, en utilisant l'API runtime.sendMessage(). Cela est dû à la limitation du script de contenu dans l'accès direct aux API, le storage
étant l'une des rares exceptions. Pour les fonctionnalités au-delà de ces exceptions, des messages sont envoyés aux pages d'extension avec lesquelles les scripts de contenu peuvent communiquer.
{% hint style="warning" %}
Selon le navigateur, les capacités du script de contenu peuvent varier légèrement. Pour les navigateurs basés sur Chromium, la liste des capacités est disponible dans la documentation des développeurs Chrome, et pour Firefox, le MDN sert de source principale.
Il est également à noter que les scripts de contenu ont la capacité de communiquer avec les scripts d'arrière-plan, leur permettant d'effectuer des actions et de transmettre des réponses.
{% endhint %}
Pour visualiser et déboguer les scripts de contenu dans Chrome, le menu des outils de développement de Chrome peut être accédé depuis Options > Autres outils > Outils de développement OU en appuyant sur Ctrl + Maj + I.
Une fois les outils de développement affichés, l'onglet Source doit être cliqué, suivi de l'onglet Scripts de contenu. Cela permet d'observer l'exécution des scripts de contenu en cours à partir de diverses extensions et de définir des points d'arrêt pour suivre le flux d'exécution.
Scripts de contenu injectés
{% hint style="success" %}
Notez que les Scripts de contenu ne sont pas obligatoires car il est également possible de injecter dynamiquement des scripts et de les injecter de manière programmatique dans les pages web via tabs.executeScript
. Cela offre en fait un contrôle plus granulaire.
{% endhint %}
Pour l'injection programmatique d'un script de contenu, l'extension doit avoir les permissions d'hôte pour la page dans laquelle les scripts doivent être injectés. Ces permissions peuvent être sécurisées soit en les demandant dans le manifeste de l'extension, soit de manière temporaire via activeTab.
Exemple d'extension basée sur activeTab
{% code title="manifest.json" %}
{
"name": "My extension",
...
"permissions": [
"activeTab",
"scripting"
],
"background": {
"service_worker": "background.js"
},
"action": {
"default_title": "Action Button"
}
}
{% endcode %}
- Injecter un fichier JS au clic :
// content-script.js
document.body.style.backgroundColor = "orange";
//service-worker.js - Inject the JS file
chrome.action.onClicked.addListener((tab) => {
chrome.scripting.executeScript({
target: { tabId: tab.id },
files: ["content-script.js"]
});
});
- Injecter une fonction au clic :
//service-worker.js - Inject a function
function injectedFunction() {
document.body.style.backgroundColor = "orange";
}
chrome.action.onClicked.addListener((tab) => {
chrome.scripting.executeScript({
target : {tabId : tab.id},
func : injectedFunction,
});
});
Exemple avec autorisations de script
// service-workser.js
chrome.scripting.registerContentScripts([{
id : "test",
matches : [ "https://*.example.com/*" ],
excludeMatches : [ "*://*/*business*" ],
js : [ "contentScript.js" ],
}]);
// Another example
chrome.tabs.executeScript(tabId, { file: "content_script.js" });
Pour inclure ou exclure plus d'URL, il est également possible d'utiliser include_globs
et exclude_globs
.
Scripts de contenu run_at
Le champ run_at
contrôle quand les fichiers JavaScript sont injectés dans la page web. La valeur préférée et par défaut est "document_idle"
.
Les valeurs possibles sont :
document_idle
: Chaque fois que possibledocument_start
: Après tout fichiercss
, mais avant que tout autre DOM ne soit construit ou qu'un autre script ne soit exécuté.document_end
: Immédiatement après que le DOM est complet, mais avant que des sous-ressources comme les images et les cadres ne soient chargées.
Via manifest.json
{
"name": "My extension",
...
"content_scripts": [
{
"matches": ["https://*.example.com/*"],
"run_at": "document_idle",
"js": ["contentScript.js"]
}
],
...
}
Via service-worker.js
chrome.scripting.registerContentScripts([{
id : "test",
matches : [ "https://*.example.com/*" ],
runAt : "document_idle",
js : [ "contentScript.js" ],
}]);
arrière-plan
Les messages envoyés par les scripts de contenu sont reçus par la page d'arrière-plan, qui joue un rôle central dans la coordination des composants de l'extension. Notamment, la page d'arrière-plan persiste tout au long de la durée de vie de l'extension, fonctionnant discrètement sans interaction directe de l'utilisateur. Elle possède son propre Modèle d'Objet de Document (DOM), permettant des interactions complexes et une gestion de l'état.
Points Clés:
- Rôle de la Page d'Arrière-plan: Agit comme le centre névralgique de l'extension, assurant la communication et la coordination entre les différentes parties de l'extension.
- Persistance: C'est une entité toujours présente, invisible pour l'utilisateur mais essentielle au fonctionnement de l'extension.
- Génération Automatique: Si elle n'est pas explicitement définie, le navigateur créera automatiquement une page d'arrière-plan. Cette page générée automatiquement inclura tous les scripts d'arrière-plan spécifiés dans le manifeste de l'extension, garantissant le bon fonctionnement des tâches d'arrière-plan de l'extension.
{% hint style="success" %} La commodité offerte par le navigateur en générant automatiquement une page d'arrière-plan (lorsqu'elle n'est pas explicitement déclarée) garantit que tous les scripts d'arrière-plan nécessaires sont intégrés et opérationnels, simplifiant le processus de configuration de l'extension. {% endhint %}
Exemple de script d'arrière-plan:
chrome.runtime.onMessage.addListener((request, sender, sendResponse) =>
{
if (request == "explain")
{
chrome.tabs.create({ url: "https://example.net/explanation" });
}
})
Il utilise l'API runtime.onMessage pour écouter les messages. Lorsqu'un message "explain"
est reçu, il utilise l'API tabs pour ouvrir une page dans un nouvel onglet.
Pour déboguer le script arrière-plan, vous pouvez accéder aux détails de l'extension et inspecter le service worker, cela ouvrira les outils de développement avec le script arrière-plan :
Pages d'options et autres
Les extensions de navigateur peuvent contenir différents types de pages :
- Les pages d'action s'affichent dans un menu déroulant lorsque l'icône de l'extension est cliquée.
- Les pages que l'extension chargera dans un nouvel onglet.
- Pages d'options : Cette page s'affiche en haut de l'extension lorsqu'elle est cliquée. Dans le manifest précédent, j'ai pu accéder à cette page en
chrome://extensions/?options=fadlhnelkbeojnebcbkacjilhnbjfjca
ou en cliquant sur :
Notez que ces pages ne sont pas persistantes comme les pages d'arrière-plan car elles chargent dynamiquement du contenu en cas de nécessité. Malgré cela, elles partagent certaines capacités avec la page d'arrière-plan :
- Communication avec les scripts de contenu : Similaire à la page d'arrière-plan, ces pages peuvent recevoir des messages des scripts de contenu, facilitant l'interaction au sein de l'extension.
- Accès aux API spécifiques à l'extension : Ces pages bénéficient d'un accès complet aux API spécifiques à l'extension, sous réserve des autorisations définies pour l'extension.
permissions
& host_permissions
permissions
et host_permissions
sont des entrées du manifest.json
qui indiqueront quelles autorisations les extensions de navigateur possèdent (stockage, localisation...) et dans quelles pages web.
Comme les extensions de navigateur peuvent être si privilégiées, une malveillante ou compromise pourrait permettre à l'attaquant différents moyens de voler des informations sensibles et d'espionner l'utilisateur.
Découvrez comment ces paramètres fonctionnent et comment ils pourraient être abusés dans :
{% content-ref url="browext-permissions-and-host_permissions.md" %} browext-permissions-and-host_permissions.md {% endcontent-ref %}
content_security_policy
Une politique de sécurité du contenu peut également être déclarée dans le manifest.json
. Si une est définie, elle pourrait être vulnérable.
Le paramètre par défaut pour les pages d'extension de navigateur est plutôt restrictif :
script-src 'self'; object-src 'self';
Pour plus d'informations sur CSP et les éventuelles contournements, consultez :
{% content-ref url="../content-security-policy-csp-bypass/" %} content-security-policy-csp-bypass {% endcontent-ref %}
web_accessible_resources
pour qu'une page web puisse accéder à une page d'une extension de navigateur, une page .html
par exemple, cette page doit être mentionnée dans le champ web_accessible_resources
du fichier manifest.json
.
Par exemple :
{
...
"web_accessible_resources": [
{
"resources": [ "images/*.png" ],
"matches": [ "https://example.com/*" ]
},
{
"resources": [ "fonts/*.woff" ],
"matches": [ "https://example.com/*" ]
}
],
...
}
Ces pages sont accessibles via des URL comme :
chrome-extension://<extension-id>/message.html
Dans les extensions publiques, l'identifiant de l'extension est accessible :
Cependant, si le paramètre manifest.json
use_dynamic_url
est utilisé, cet identifiant peut être dynamique.
Le fait de pouvoir accéder à ces pages rend ces pages potentiellement vulnérables au ClickJacking :
{% content-ref url="browext-clickjacking.md" %} browext-clickjacking.md {% endcontent-ref %}
{% hint style="success" %} Le fait de permettre le chargement de ces pages uniquement par l'extension et non par des URL aléatoires pourrait prévenir les attaques de ClickJacking. {% endhint %}
externally_connectable
Selon la documentation, la propriété de manifeste "externally_connectable"
déclare quelles extensions et quelles pages web peuvent se connecter à votre extension via runtime.connect et runtime.sendMessage.
- Si la clé
externally_connectable
n'est pas déclarée dans le manifeste de votre extension ou si elle est déclarée comme"ids": ["*"]
, toutes les extensions peuvent se connecter, mais aucune page web ne peut se connecter. - Si des IDs spécifiques sont spécifiés, comme dans
"ids": ["aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"]
, seules ces applications peuvent se connecter. - Si des correspondances sont spécifiées, ces applications web pourront se connecter :
"matches": [
"https://*.google.com/*",
"*://*.chromium.org/*",
- Si elle est spécifiée comme vide :
"externally_connectable": {}
, aucune application ou site web ne pourra se connecter.
Moins il y a d'extensions et d'URL indiquées ici, plus petite sera la surface d'attaque.
{% hint style="danger" %}
Si une page web vulnérable aux attaques XSS ou à la prise de contrôle est indiquée dans externally_connectable
, un attaquant pourra envoyer des messages directement au script arrière-plan, contournant complètement le Content Script et sa CSP.
Il s'agit donc d'une échappatoire très puissante.
De plus, si le client installe une extension malveillante, même si elle n'est pas autorisée à communiquer avec l'extension vulnérable, elle pourrait injecter des données XSS dans une page web autorisée ou abuser des APIs WebRequest
ou DeclarativeNetRequest
pour manipuler les requêtes sur un domaine ciblé en modifiant une requête de page pour un fichier JavaScript. (Notez que la CSP sur la page ciblée pourrait empêcher ces attaques). Cette idée provient de cette analyse.
{% endhint %}
Communication entre le Web ↔︎ le Content Script
Les environnements où les scripts de contenu opèrent et où les pages hôtes existent sont séparés les uns des autres, assurant une isolation. Malgré cette isolation, les deux ont la capacité d'interagir avec le Modèle d'Objet de Document (DOM) de la page, une ressource partagée. Pour que la page hôte puisse communiquer avec le script de contenu, ou indirectement avec l'extension via le script de contenu, il est nécessaire d'utiliser le DOM accessible par les deux parties comme canal de communication.
Messages Postés
{% code title="content-script.js" %}
var port = chrome.runtime.connect();
window.addEventListener("message", (event) => {
// We only accept messages from ourselves
if (event.source !== window) {
return;
}
if (event.data.type && (event.data.type === "FROM_PAGE")) {
console.log("Content script received: " + event.data.text);
port.postMessage(event.data.text);
}
}, false);
{% endcode %}
{% code title="example.js" %}
document.getElementById("theButton").addEventListener("click", () => {
window.postMessage(
{type : "FROM_PAGE", text : "Hello from the webpage!"}, "*");
}, false);
{% endcode %}
Une communication sécurisée par Post Message devrait vérifier l'authenticité du message reçu, cela peut être fait en vérifiant :
event.isTrusted
: Cela est vrai uniquement si l'événement a été déclenché par une action de l'utilisateur- Le script de contenu peut s'attendre à un message uniquement si l'utilisateur effectue une action
- Domaine d'origine : peut s'attendre à un message uniquement à partir d'une liste blanche de domaines.
- Si une expression régulière est utilisée, soyez très prudent
- Source :
received_message.source !== window
peut être utilisé pour vérifier si le message provient de la même fenêtre où le script de contenu écoute.
Les vérifications précédentes, même si elles sont effectuées, pourraient être vulnérables, donc vérifiez dans la page suivante les bypass potentiels de Post Message :
{% content-ref url="../postmessage-vulnerabilities/" %} postmessage-vulnerabilities {% endcontent-ref %}
Iframe
Une autre façon possible de communication pourrait être à travers les URLs Iframe, vous pouvez trouver un exemple dans :
{% content-ref url="browext-xss-example.md" %} browext-xss-example.md {% endcontent-ref %}
DOM
Ce n'est pas "exactement" un moyen de communication, mais le web et le script de contenu auront accès au DOM web. Donc, si le script de contenu lit des informations à partir de celui-ci, faisant confiance au DOM web, le web pourrait modifier ces données (car le web ne devrait pas être digne de confiance, ou parce que le web est vulnérable aux XSS) et compromettre le script de contenu.
Vous pouvez également trouver un exemple de XSS basé sur le DOM pour compromettre une extension de navigateur dans :
{% content-ref url="browext-xss-example.md" %} browext-xss-example.md {% endcontent-ref %}
Informations Sensibles en Mémoire/Code
Si une extension de navigateur stocke des informations sensibles dans sa mémoire, celles-ci pourraient être extraites (surtout sur les machines Windows) et recherchées pour ces informations.
Par conséquent, la mémoire de l'extension de navigateur ne devrait pas être considérée comme sécurisée et les informations sensibles telles que les identifiants ou les phrases mnémoniques ne devraient pas être stockées.
Bien sûr, ne mettez pas d'informations sensibles dans le code, car elles seront publiques.
Pour extraire la mémoire du navigateur, vous pourriez extraire la mémoire du processus ou aller dans les paramètres de l'extension de navigateur, cliquer sur Inspecter la fenêtre contextuelle
-> Dans la section Mémoire
-> Prendre un instantané
et CTRL+F
pour rechercher à l'intérieur de l'instantané des informations sensibles.
Communication Script de Contenu ↔︎ Script d'Arrière-plan
Un script de contenu peut utiliser les fonctions runtime.sendMessage() ou tabs.sendMessage() pour envoyer un message sérialisable en JSON une seule fois.
Pour gérer la réponse, utilisez la Promise retournée. Cependant, pour des raisons de compatibilité ascendante, vous pouvez toujours passer un callback en dernier argument.
Envoyer une requête à partir d'un script de contenu ressemble à ceci :
(async () => {
const response = await chrome.runtime.sendMessage({greeting: "hello"});
// do something with response here, not outside the function
console.log(response);
})();
Envoyer une requête depuis l'extension (généralement un script arrière-plan). Un script de contenu peut utiliser les fonctions, à condition de spécifier l'onglet auquel l'envoyer. Exemple de comment envoyer un message au script de contenu dans l'onglet sélectionné :
// From https://stackoverflow.com/questions/36153999/how-to-send-a-message-between-chrome-extension-popup-and-content-script
(async () => {
const [tab] = await chrome.tabs.query({active: true, lastFocusedWindow: true});
const response = await chrome.tabs.sendMessage(tab.id, {greeting: "hello"});
// do something with response here, not outside the function
console.log(response);
})();
Sur le côté récepteur, vous devez configurer un runtime.onMessage écouteur d'événements pour gérer le message. Cela ressemble de la même manière depuis un script de contenu ou une page d'extension.
// From https://stackoverflow.com/questions/70406787/javascript-send-message-from-content-js-to-background-js
chrome.runtime.onMessage.addListener(
function(request, sender, sendResponse) {
console.log(sender.tab ?
"from a content script:" + sender.tab.url :
"from the extension");
if (request.greeting === "hello")
sendResponse({farewell: "goodbye"});
}
);
Dans l'exemple mis en évidence, sendResponse()
a été exécuté de manière synchrone. Pour modifier le gestionnaire d'événements onMessage
pour une exécution asynchrone de sendResponse()
, il est impératif d'incorporer return true;
.
Une considération importante est que dans les scénarios où plusieurs pages sont configurées pour recevoir des événements onMessage
, la première page à exécuter sendResponse()
pour un événement spécifique sera la seule capable de délivrer efficacement la réponse. Toutes les réponses ultérieures au même événement ne seront pas prises en compte.
Lors de la création de nouvelles extensions, la préférence devrait être donnée aux promesses plutôt qu'aux rappels. En ce qui concerne l'utilisation des rappels, la fonction sendResponse()
est considérée comme valide uniquement si elle est exécutée directement dans le contexte synchrone, ou si le gestionnaire d'événements indique une opération asynchrone en retournant true
. Si aucun des gestionnaires ne retourne true
ou si la fonction sendResponse()
est supprimée de la mémoire (collecte des déchets), le rappel associé à la fonction sendMessage()
sera déclenché par défaut.
Chargement d'une extension dans le navigateur
- Téléchargez l'extension du navigateur et décompressez-la
- Allez à
chrome://extensions/
et activez leMode développeur
- Cliquez sur le bouton
Charger l'extension non empaquetée
Sur Firefox, allez à about:debugging#/runtime/this-firefox
et cliquez sur le bouton Charger un module complémentaire temporaire
.
Obtenir le code source depuis le magasin
Le code source d'une extension Chrome peut être obtenu par divers moyens. Ci-dessous se trouvent des explications détaillées et des instructions pour chaque option.
Télécharger l'extension au format ZIP via la ligne de commande
Le code source d'une extension Chrome peut être téléchargé sous forme de fichier ZIP en utilisant la ligne de commande. Cela implique d'utiliser curl
pour récupérer le fichier ZIP à partir d'une URL spécifique, puis d'extraire le contenu du fichier ZIP dans un répertoire. Voici les étapes :
- Remplacez
"extension_id"
par l'identifiant réel de l'extension. - Exécutez les commandes suivantes :
extension_id=your_extension_id # Replace with the actual extension ID
curl -L -o "$extension_id.zip" "https://clients2.google.com/service/update2/crx?response=redirect&os=mac&arch=x86-64&nacl_arch=x86-64&prod=chromecrx&prodchannel=stable&prodversion=44.0.2403.130&x=id%3D$extension_id%26uc"
unzip -d "$extension_id-source" "$extension_id.zip"
Utiliser le site CRX Viewer
Utiliser l'extension CRX Viewer
Une autre méthode pratique consiste à utiliser le Chrome Extension Source Viewer, qui est un projet open-source. Il peut être installé depuis le Chrome Web Store. Le code source du visualiseur est disponible dans son dépôt GitHub.
Voir la source de l'extension installée localement
Les extensions Chrome installées localement peuvent également être inspectées. Voici comment procéder :
- Accédez au répertoire de profil local de Chrome en visitant
chrome://version/
et en localisant le champ "Chemin du profil". - Naviguez jusqu'au sous-dossier
Extensions/
dans le répertoire du profil. - Ce dossier contient toutes les extensions installées, généralement avec leur code source dans un format lisible.
Pour identifier les extensions, vous pouvez faire correspondre leurs ID à leurs noms :
- Activez le mode développeur sur la page
about:extensions
pour voir les ID de chaque extension. - À l'intérieur du dossier de chaque extension, le fichier
manifest.json
contient un champname
lisible, vous aidant à identifier l'extension.
Utiliser un archiveur de fichiers ou un décompresseur
Allez sur le Chrome Web Store et téléchargez l'extension. Le fichier aura une extension .crx
. Changez l'extension du fichier de .crx
à .zip
. Utilisez n'importe quel archiveur de fichiers (comme WinRAR, 7-Zip, etc.) pour extraire le contenu du fichier ZIP.
Utiliser le mode développeur dans Chrome
Ouvrez Chrome et allez à chrome://extensions/
. Activez le "Mode développeur" en haut à droite. Cliquez sur "Charger l'extension non empaquetée...". Naviguez jusqu'au répertoire de votre extension. Cela ne télécharge pas le code source, mais c'est utile pour visualiser et modifier le code d'une extension déjà téléchargée ou développée.
Liste de vérification d'audit de sécurité
Bien que les extensions de navigateur aient une surface d'attaque limitée, certaines d'entre elles pourraient contenir des vulnérabilités ou des améliorations potentielles de renforcement. Voici les plus courantes :
- Limitez autant que possible les
permissions
demandées - Limitez autant que possible les
host_permissions
- Utilisez une
content_security_policy
forte - Limitez autant que possible les
externally_connectable
, s'il n'est pas nécessaire et possible, ne le laissez pas par défaut, spécifiez{}
- Si une URL vulnérable aux attaques XSS ou à la prise de contrôle est mentionnée ici, un attaquant pourra envoyer des messages directement aux scripts d'arrière-plan. Une faille très puissante.
- Limitez autant que possible les
web_accessible_resources
, même vide si possible. - Si
web_accessible_resources
n'est pas vide, vérifiez le ClickJacking - Si une communication se produit de l'extension à la page web, vérifiez les vulnérabilités XSS causées par la communication.
- Si des messages Post sont utilisés, vérifiez les vulnérabilités des messages Post.
- Si le Script de contenu accède aux détails du DOM, vérifiez qu'ils n'introduisent pas de XSS s'ils sont modifiés par le web
- Mettez un accent particulier si cette communication est également impliquée dans la communication Script de contenu -> Script d'arrière-plan
- Les informations sensibles ne doivent pas être stockées dans le code de l'extension de navigateur
- Les informations sensibles ne doivent pas être stockées dans la mémoire de l'extension de navigateur
Outils
Tarnish
- Récupère n'importe quelle extension Chrome à partir d'un lien fourni par le Chrome Web Store.
- Visionneur de manifest.json : affiche simplement une version JSON mise en forme du manifeste de l'extension.
- Analyse d'empreinte digitale : Détection des web_accessible_resources et génération automatique de JavaScript d'empreinte digitale d'extension Chrome.
- Analyse potentielle de Clickjacking : Détection des pages HTML d'extension avec la directive web_accessible_resources définie. Elles sont potentiellement vulnérables au clickjacking en fonction de l'objectif des pages.
- Visionneur d'avertissement(s) de permission : qui affiche une liste de tous les avertissements de permission Chrome qui s'afficheront lorsqu'un utilisateur tentera d'installer l'extension.
- Fonction(s) dangereuse(s) : montre l'emplacement des fonctions dangereuses qui pourraient potentiellement être exploitées par un attaquant (par exemple, des fonctions telles que innerHTML, chrome.tabs.executeScript).
- Point(s) d'entrée : montre où l'extension prend en compte les entrées utilisateur/externes. Cela est utile pour comprendre la surface d'une extension et rechercher des points potentiels pour envoyer des données malveillantes à l'extension.
- Les scanners de Fonction(s) dangereuse(s) et de Point(s) d'entrée ont les éléments suivants pour leurs alertes générées :
- Extrait de code pertinent et ligne ayant provoqué l'alerte.
- Description du problème.
- Un bouton "Voir le fichier" pour voir le fichier source complet contenant le code.
- Le chemin du fichier alerté.
- L'URI complet de l'extension Chrome du fichier alerté.
- Le type de fichier, tel qu'un script de page d'arrière-plan, un script de contenu, une action de navigateur, etc.
- Si la ligne vulnérable est dans un fichier JavaScript, les chemins de toutes les pages où elle est incluse ainsi que le type de ces pages, et l'état de web_accessible_resource.
- Analyseur de stratégie de sécurité du contenu (CSP) et vérificateur de contournement : Cela mettra en évidence les faiblesses de la CSP de votre extension et illuminera également les éventuelles façons de contourner votre CSP en raison des CDN autorisés, etc.
- Bibliothèques connues vulnérables : Cela utilise Retire.js pour vérifier toute utilisation de bibliothèques JavaScript connues comme vulnérables.
- Télécharger l'extension et les versions formatées.
- Télécharger l'extension originale.
- Télécharger une version embelli de l'extension (HTML et JavaScript automatiquement mis en forme).
- Mise en cache automatique des résultats d'analyse, lancer une analyse d'extension prendra beaucoup de temps la première fois que vous l'exécutez. Cependant, la deuxième fois, en supposant que l'extension n'ait pas été mise à jour, sera presque instantanée en raison de la mise en cache des résultats.
- URLs de rapport liables, permettant de facilement partager un rapport d'extension généré par tarnish avec quelqu'un d'autre.
Neto
Le projet Neto est un package Python 3 conçu pour analyser et dévoiler les fonctionnalités cachées des plugins et extensions de navigateur pour des navigateurs bien connus tels que Firefox et Chrome. Il automatise le processus de décompression des fichiers empaquetés pour extraire ces fonctionnalités des ressources pertinentes dans une extension comme manifest.json
, les dossiers de localisation ou les fichiers source Javascript et HTML.
Références
- Merci à @naivenom pour l'aide apportée à cette méthodologie
- https://www.cobalt.io/blog/introduction-to-chrome-browser-extension-security-testing
- https://palant.info/2022/08/10/anatomy-of-a-basic-extension/
- https://palant.info/2022/08/24/attack-surface-of-extension-pages/
- https://palant.info/2022/08/31/when-extension-pages-are-web-accessible/
- https://help.passbolt.com/assets/files/PBL-02-report.pdf
- https://developer.chrome.com/docs/extensions/develop/concepts/content-scripts
- https://developer.chrome.com/docs/extensions/mv2/background-pages
- https://thehackerblog.com/kicking-the-rims-a-guide-for-securely-writing-and-auditing-chrome-extensions/
- https://gist.github.com/LongJohnCoder/9ddf5735df3a4f2e9559665fb864eac0
Apprenez le piratage AWS de zéro à héros avec htARTE (HackTricks AWS Red Team Expert)!
D'autres façons de soutenir HackTricks:
- Si vous souhaitez voir votre entreprise annoncée dans HackTricks ou télécharger HackTricks en PDF, consultez les PLANS D'ABONNEMENT !
- Obtenez le swag officiel PEASS & HackTricks
- Découvrez La famille PEASS, notre collection exclusive de NFTs
- Rejoignez le 💬 groupe Discord ou le groupe Telegram ou suivez-nous sur Twitter 🐦 @carlospolopm.
- Partagez vos astuces de piratage en soumettant des PR aux HackTricks et HackTricks Cloud dépôts GitHub.