3 points par GN⁺ 2023-07-14 | 1 commentaires | Partager sur WhatsApp
  • Le nom d’hôte local par défaut de macOS peut inclure le nom de l’utilisateur, ce qui permet à un site web, sans autorisation, de réduire les candidats via les différences de temps de résolution mDNS
  • Un attaquant combine 50 prénoms populaires selon le pays et le genre avec des candidats de noms d’appareils ; dans les expériences, il a trouvé le nom d’utilisateurs macOS dans 65 % des cas en moyenne
  • Le JavaScript du navigateur ne peut pas ouvrir de sockets UDP arbitraires, mais il peut comparer les délais de réponse d’adresses en .local via des requêtes fetch, iframe, Image et WebRTC
  • Des informations comme le fuseau horaire, la langue, la localisation IP, navigator.language de Safari, la résolution d’écran et screen.isExtended servent à réduire les candidats de locale et de modèle d’appareil
  • L’aspect pratique est limité et l’activité est facile à repérer dans l’onglet réseau des outils de développement, mais la même méthode d’exploration mDNS peut aussi servir à détecter des imprimantes, smart TV, enceintes connectées et objets IoT

La structure de fuite de nom dans le nom d’hôte local de macOS

  • Le vrai nom d’un utilisateur macOS peut être estimé depuis le navigateur sans demande d’autorisation ; le point clé est le protocole mDNS et le format par défaut du nom d’hôte local
  • Même en n’utilisant qu’une liste de 50 prénoms populaires par genre pour un pays donné, le bon prénom d’un utilisateur macOS est détecté dans 65 % des cas en moyenne
  • Fingerprint n’utilise pas cette technique dans son produit et ne fournit pas de service de suivi cross-site
  • Le but de cette discussion publique est d’aider les éditeurs de navigateurs à corriger rapidement ce type de technique

Comment fonctionnent mDNS et Apple Bonjour

  • multicast DNS est un protocole servant à enregistrer, découvrir et diffuser des noms d’appareils sur un réseau local
  • Des appareils comme les imprimantes envoient des paquets d’enregistrement UDP vers l’IP interne réservée 224.0.0.251, qui peut contenir des noms d’hôte comme HP_LaserJet_Printer.local
  • Le domaine de premier niveau .local indique que ce nom d’hôte doit être résolu via mDNS
  • Les routeurs diffusent automatiquement ces paquets aux autres appareils du réseau local afin qu’ils puissent mettre ces noms d’hôte en cache
  • Les appareils envoient aussi des paquets de requête vers la même IP réservée pour rechercher un appareil portant un nom spécifique potentiellement présent sur le réseau
  • Exemples de noms d’hôte :
    • johns-mac-mini.local
    • david-ZenBook-UX431DA-UM431DA.local
    • james-iphone.local
    • canon-mf644c.local
    • bedroom-appletv.local
    • dlinkrouter.local
  • Sur les appareils Apple, mDNS est largement utilisé dans le cadre de la fonctionnalité Apple Bonjour
  • Le nom d’utilisateur peut apparaître dans le nom d’hôte local par défaut ; sur macOS, ce nom peut être consulté ou modifié dans Réglages Système > Partage

Méthode de contournement pour vérifier des noms d’hôte mDNS depuis le navigateur

  • mDNS repose sur des paquets UDP, et l’environnement JavaScript du navigateur ne permet donc pas de l’utiliser directement via des sockets UDP arbitraires
  • À la place, l’attaque exploite le fait que le navigateur tente de résoudre le nom d’hôte d’une URL pour mener une attaque par temporisation
  • La preuve de concept consiste à envoyer des requêtes GET fetch ordinaires vers device-1.local, qui existe, et device-2.local, qui n’existe pas
  • Si l’adresse est résolue, le navigateur envoie alors un paquet TCP vers le port 80, qui est généralement fermé
  • Au niveau réseau, les erreurs diffèrent :
    • device-1.local existe : ERR_CONNECTION_REFUSED
    • device-2.local n’existe pas : ERR_NAME_NOT_RESOLVED
  • En JavaScript, les deux erreurs sont mappées vers la même erreur Failed to fetch, on ne peut donc pas s’appuyer sur leur type
  • Comme le réseau local est rapide, un nom d’hôte mDNS valide est résolu bien avant le délai d’expiration de connexion par défaut
  • Dans l’exemple, une adresse valide répond en 4 ms, contre 5 secondes pour une adresse invalide
  • Cette approche est suffisamment cohérente pour une preuve de concept et se comporte de manière similaire dans les principaux navigateurs
  • En pratique, outre fetch, des API réseau JavaScript comme iframe, Image et WebRTC peuvent aussi servir à des attaques par temporisation sur la résolution DNS

Comment forcer par force brute le nom d’un utilisateur macOS

  • Le nom d’hôte local par défaut de macOS inclut le nom de l’utilisateur et le nom de l’appareil, et son format varie selon la locale système
    • Anglais : <name>s-macbook-pro.local
    • Français : macbook-air-de-<name>.local
    • Russe : mac-mini-<name>.local
  • Avec une approche simple, combiner les 1 000 prénoms les plus fréquents, les 10 locales les plus courantes et 5 noms d’appareils macOS classiques revient à tester 50 000 noms d’hôte
  • Dans ce cas, l’analyse complète peut prendre plus d’une heure
  • Une stratégie plus efficace consiste à limiter la recherche à une seule locale, un seul appareil et 50 prénoms courants de cette locale
  • Réduire le périmètre diminue la précision, mais raccourcit suffisamment le temps d’attaque pour rendre le scénario plus réaliste
  • Le choix de la locale peut s’appuyer sur le fuseau horaire du navigateur, la langue et la géolocalisation de l’adresse IP
  • Safari expose la locale système via la propriété navigator.language, et cette valeur correspond souvent à la locale du nom d’hôte visé
  • Une autre méthode de contournement pour déterminer le pays d’origine d’un utilisateur est la technique déjà décrite de détection de région Apple ID
  • Les candidats d’appareils peuvent être réduits grâce à la résolution d’écran
    • Par exemple, une résolution de 1728x1117 correspond probablement à un MacBook Pro 16 pouces
    • Un écran étendu peut être détecté via la propriété screen.isExtended
    • Si un écran étendu est détecté, on peut revenir à une liste de 3 à 5 appareils Apple sous macOS parmi les plus courants

Limites et autres applications possibles

  • Cette attaque est peu pratique en raison de ses faiblesses intrinsèques et de nombreuses limites
  • Sauf si l’exploitant d’un site cherche délibérément à lever l’anonymat de ses visiteurs, elle est facile à détecter dans l’onglet réseau des outils de développement du navigateur
  • En combinant cette méthode avec la détection d’applications installées, il serait possible de créer un site nuisible affichant, sans autorisation, le vrai nom d’un utilisateur et une fonction déduite de la liste des applications professionnelles qu’il utilise
  • Les appareils Apple exécutant macOS constituent l’exemple principal, mais la technique d’exploration mDNS peut être étendue de plusieurs façons
  • Elle peut aussi servir à détecter des imprimantes, smart TV, enceintes connectées et autres objets IoT domestiques via un scan du réseau local
  • Elle peut également s’appliquer aux iPhone et iPad si la synchronisation Wi‑Fi ou le débogage distant de Safari est activé

1 commentaires

 
GN⁺ 2023-07-14
Commentaires sur Hacker News
  • J’utilise Little Snitch sur macOS, et l’interface est plutôt bien faite : on peut la configurer pour demander explicitement à l’utilisateur local avant d’autoriser une requête réseau
    https://www.obdev.at/products/littlesnitch/index.html
    Ça me bloque parfois pendant une connexion à distance, en général quand une session SSH essaie de télécharger quelque chose de nouveau, par exemple des composants NodeJS depuis NPM. Le téléchargement SSH dans le terminal texte se fige, puis, une fois que je comprends que c’est Little Snitch qui en est la cause, je dois descendre jusqu’au bureau du bas, bouger la souris pour réveiller l’écran, déverrouiller l’économiseur d’écran et cliquer sur « Allow » dans la boîte de dialogue Little Snitch
    Donc, ça fonctionne comme prévu. Cela dit, ce genre d’outil est souvent configuré par défaut pour autoriser discrètement les requêtes vers le réseau local, donc je ne sais pas si la démonstration de l’article fonctionnerait aussi dans mon environnement

    • Dans mon cas, j’ai du mal à imaginer configurer LittleSnitch pour n’autoriser que certains noms d’hôte depuis le navigateur. J’ai une règle du genre « autoriser tout le trafic vers 53/80/443 », sinon la plupart des sites web feraient apparaître des centaines de pop-ups LittleSnitch
    • J’utilise NetFence sur un iPhone jailbreaké
      C’est étonnant de voir quels types de connexions socket les apps ouvrent en douce, y compris les apps bancaires
      https://havoc.app/package/netfence
    • Cela dit, Little Snitch laisse quand même fuiter l’IP lorsqu’il bloque :(
      https://news.ycombinator.com/item?id=35363343
    • J’ai essayé OpenSnitch sur Linux, un logiciel similaire. Il n’a rien détecté d’anormal, mais il s’est montré assez pénible dans la plupart des tâches de base
    • À noter que la résolution DNS a lieu avant la fenêtre pop-up d’autorisation/refus de connexion. Par exemple, www.example.com sera résolu en 1.1.1.1, mais la connexion effective à 1.1.1.1 ne sera pas établie tant que vous n’aurez pas cliqué sur Confirm
      Si vous ajoutez un Pi-hole à votre réseau, vous ne regretterez ni le temps, ni l’argent, ni l’investissement
  • Existe-t-il un moyen d’empêcher les sites du web public d’envoyer des requêtes réseau vers mon réseau local ? J’ai du mal à imaginer pourquoi cela devrait être autorisé par défaut
    Je ne suis pas en train de proposer de ressusciter les autorisations de la Local Intranet Zone d’IE

    • En général, ce n’est pas possible à cause de CORS. La seule raison pour laquelle ce « hack » fonctionne, c’est que le timing du refus diffère entre une requête vers un domaine non résolu et une requête résolue mais rejetée
      Mais même si quelque chose tourne sur https://192.168.2.1, une web app exécutée depuis https://my-own-domain.com ne pourra pas y accéder, sauf si le service sur 192.168.2.1 autorise my-own-domain.com comme Origin
    • Brave a récemment ajouté une fonctionnalité qui demande une autorisation pour l’accès au réseau local
      https://brave.com/privacy-updates/27-localhost-permission/
      Post HN : https://news.ycombinator.com/item?id=36574775
    • Une app qui abuse souvent de cette méthode, c’est l’application de bureau Discord, qui laisse un port local ouvert et à l’écoute
      Quand le navigateur arrive sur une page d’invitation à un canal Discord, il envoie une requête vers localhost via ce port et transmet l’identifiant du canal au client. L’application peut alors afficher une expérience native « Join Channel »
      Je m’en suis rendu compte en voyant que cela continuait à fonctionner même en mode navigation privée et alors que le navigateur était déconnecté de Discord. Ce n’est pas sain. Il faudrait nettement améliorer le sandboxing de toutes les applications dans l’univers desktop
    • On peut le bloquer avec un filtre statique uBlock Origin :
      ||local^$all
      Cela bloque toutes les requêtes vers .local, y compris celles provenant de .local lui-même. Si vous avez besoin d’autoriser foo.local à communiquer avec lui-même, par exemple parce que vous faites tourner un serveur web, il faut ajouter une exception supplémentaire pour chaque domaine :
      @@||foo.local^$domain=foo.local,all
      Ou, si vous faites confiance à tout .local et voulez autoriser n’importe quel foo.local à parler à n’importe quel bar.local, vous pouvez ajouter une exception globale pour .local :
      @@||local^$domain=local,all
    • Pour éviter toute confusion, le problème n’est pas qu’un serveur sur Internet envoie des requêtes vers le réseau local, mais que le navigateur web local envoie ces requêtes. Bien sûr, le JavaScript exécuté dans le navigateur peut être chargé depuis un serveur sur Internet
  • Avec le temps, j’ai de plus en plus le sentiment qu’il vaut mieux utiliser Internet depuis une box Qubes, dans une VM Whonix/Tor jetable, avec JavaScript désactivé
    C’est vraiment répugnant. Pas surprenant, mais le simple fait que ce soit possible est horrible à bien des égards
    Si vous ne connaissez pas fingerprint.com, ils font du « profilage utilisateur profond ». En gros, ils arrivent à conserver le même identifiant utilisateur même si l’ordinateur, le navigateur ou le système d’exploitation changent. Il y a une démo sur leur page d’accueil, et c’est un peu glaçant de voir à quel point ça marche bien

    • Il reconnaît totalement le même appareil même derrière des IP VPN différentes. Vraiment flippant
    • C’est répugnant. Le fait qu’ils y arrivent en mode navigation privée sur un iPhone standard, même après avoir changé deux fois d’adresse IP, est impressionnant, alors que cet iPhone devrait pourtant sembler identique à tous les autres iPhone
      Filtre uBlock Origin pour casser la démo :
      ||fpjscdn.net
  • Une attaque temporelle du même genre peut permettre de scanner les ports de la machine locale et d’autres appareils du réseau local depuis le navigateur
    https://github.com/Flu1dTeam/PortScanner
    eBay s’était déjà fait prendre à faire ça autrefois
    https://blog.nem.ec/2020/05/24/ebay-port-scanning/

    • Quoi ? C’est hyper flippant, comment ça se fait que je n’en aie jamais entendu parler avant ?
  • Heureusement que je change toujours le nom de mes appareils
    Le schéma de nommage par défaut d’Apple est une erreur de confidentialité. J’ai eu un premier rendez-vous avec une personne des forces de l’ordre ; elle était venue seule, c’était une femme clairement soucieuse de sa sécurité, elle m’a dit qu’elle avait fait des recherches sur moi et communiqué notre position à quelques personnes de sa communauté
    Moi, à l’inverse, je ne connaissais même pas son nom de famille, et j’en faisais une blague. Après le dîner, quand on est montés en voiture, l’écran du tableau de bord a affiché que l’iPhone s’était appairé automatiquement, et son nom était défini avec son prénom et son nom. J’ai trouvé ça intéressant. Je ne l’ai pas mentionné et, jusqu’à la fin du trajet, je lui ai demandé de deviner comment j’avais appris son nom

    • Il arrive très souvent que des voitures de location conservent une dizaine de profils de téléphones précédemment appairés, avec le répertoire, des emplacements enregistrés sur la carte et même l’historique. Bien sûr, ce n’est pas très utile, mais les informations fuitent sans que personne n’y pense
      Le plus difficile, c’est surtout de penser à supprimer mon propre profil avant de rendre la voiture
  • Dans l’exemple ci-dessus, une adresse valide prend 4 millisecondes, une adresse invalide 5 secondes
    C’est surprenant. Je m’attendais à ce qu’un échec de résolution DNS soit bien plus rapide que le délai d’expiration de connexion par défaut qui suit une résolution DNS réussie
    Cela dit, j’ai toujours trouvé que s-mac-xxxx était un choix un peu étrange. Encore plus pour une entreprise qui met autant en avant la confidentialité comme argument commercial. On pouvait s’attendre à ce qu’ils n’utilisent pas de vrais noms, ou bien qu’ici la « convivialité » ait primé. Du point de vue de la confidentialité, les noms d’hôte générés aléatoirement par Windows sont meilleurs

    • Le DNS classique pose une question oui/non à un seul serveur sur une seule IP, mais mDNS est multicast, donc aucun serveur ne peut répondre de manière autoritaire « non »†. On ne peut détecter l’absence d’un enregistrement que lorsque la requête expire faute de réponse du serveur
      † À strictement parler, ce n’est pas tout à fait exact. Si un appareil sait qu’il possède ce nom, il peut répondre non
    • Si le vrai nom de l’utilisateur se retrouve dans le nom d’hôte, c’est peut-être à cause d’AirDrop. Le système semble utiliser le nom d’hôte pour des fonctions comme Personal Hotspot ou AirDrop, et d’autres types de noms risqueraient de créer une confusion généralisée lors du partage de fichiers
    • En plus de la question du délai d’expiration de connexion par défaut, ici il y a aussi le fait qu’on a reçu un connection refused, c’est-à-dire un RST, et non un délai d’expiration de connexion
  • L’article est bien écrit et intéressant. J’apprécie particulièrement le ton sans exagération, du genre « compte tenu des faiblesses intrinsèques et des nombreuses limitations, cette attaque n’est pas pratique »

    • Dans un autre univers, ça serait devenu « FINGERBleed », avec un site web tape-à-l’œil et même un logo
    • Je n’en suis pas certain
      Cette méthode permet de tester si certains noms d’hôte existent sur le réseau
      Avec un seul nom d’hôte unique, ce n’est peut-être pas très grave, mais qu’en est-il des noms d’hôte fixes ou par défaut, courants dans l’univers IoT ?
      Un site web pourrait deviner en douce si un utilisateur possède un appareil précis. Et ce serait pire dans le cadre d’attaques ciblées. Si l’on connaît déjà certains appareils du réseau, on peut deviner si l’utilisateur connecté se trouve dans le réseau visé
  • Si seulement désactiver JavaScript ne désactivait pas aussi l’expérience utilisateur finale

    • C’est la seule raison pour laquelle je ne peux pas désactiver JavaScript globalement
      Mais à l’avenir, j’aurai probablement de plus en plus l’impression de devoir le laisser désactivé par défaut à cause des préoccupations liées à la confidentialité
    • N’existe-t-il pas un moyen de limiter fortement ce que le moteur JavaScript peut faire ?
  • Heureusement, le nom de mes appareils est en général du style « MacBook Pro de xxxs (34) ». Ce n’est pas un bug, c’est une fonctionnalité

    • Définissez le nom d’utilisateur du portable sur user et le nom d’hôte sur hostname. Plus il y aura de gens à faire ça, mieux ce sera
  • Intéressant, bien écrit, et il y a même une preuve de concept correcte. Beau travail
    Comme contre-mesure amusante, on pourrait renommer le nom d’hôte de l’appareil en quelque chose comme atemptingurl.local, histoire de donner envie à l’attaquant de visiter ce site. Cette page serait alors soigneusement conçue pour lui appliquer la même technique, avec un message du genre :
    « Bonjour [nom de l’appareil du hacker] ! Les informations sur votre machine, votre adresse IP, votre position géographique et d’autres données d’empreinte ont été collectées et signalées à [insérer le nom d’une agence cyber terrifiante]. » Même si l’attaquant est un vétéran expérimenté et non un simple script kiddie, ça pourrait au moins le faire rire
    Les gens ont besoin de plus de raisons de rire :-)

    • Pour faire ça, il faudrait faire tourner un serveur HTTP avec CORS totalement ouvert. On s’exposerait alors à tous les bugs du serveur HTTP choisi, ce qui réduirait aussi sa propre sécurité