Un code QR qui mène vers différentes destinations grâce à un procédé lenticulaire et adversarial
(mstdn.social/@isziaui)- En partant de l’expérience de Guy Dupont sur des codes QR selon l’angle, Christian Walther a réussi à créer un code QR qui, même sans lentille, est lu comme menant vers différentes destinations selon les conditions de scan
- La structure clé est un masque en damier qui superpose deux codes QR de même taille en répartissant leurs pixels
- Si le lecteur de QR échantillonne le centre des pixels attendus, un léger déplacement de l’image peut faire basculer les points d’échantillonnage vers l’un des deux codes et produire un résultat différent
- Dans les essais, le damier fonctionnait mieux que des rayures verticales ou diagonales, et un niveau élevé de correction d’erreurs semblait avantageux, même si les résultats variaient encore selon les décodeurs
- Cela montre qu’une seule image QR peut être interprétée de plusieurs façons selon l’angle, le déplacement, l’implémentation du décodeur, ainsi que le traitement des couleurs et du canal alpha
Un double code QR sans lentille
- Guy Dupont a expérimenté un code QR qui renvoie vers des sources différentes selon l’angle, à partir de l’idée de « différents points de vue sur une même histoire »
- Christian Walther a repris cette idée en se demandant si cela pouvait fonctionner sans lentille, et affirme avoir créé une image QR qui marche réellement
- Dupont a réagi en disant qu’il avait bien lu les deux destinations, GitHub et Mastodon, dans le résultat de Walther
- Matt Lacey a lui aussi indiqué que, sur son téléphone, l’URL Mastodon était détectée plus facilement, mais que l’URL GitHub était également lisible
Une composition qui partage les pixels en deux
- Le principe de base consiste à créer deux codes QR de même taille, puis à les superposer en une seule image
- La moitié de chaque pixel provient d’un des codes QR
- L’autre moitié provient de l’autre code
- Dans l’explication, un code est visible dans les quadrants supérieur gauche et inférieur droit de chaque pixel, tandis que l’autre apparaît dans les zones restantes
- Côté fabrication, il est suggéré qu’un masque de calque à motif en damier a pu être rempli dans Photoshop
Pourquoi le résultat du scan diverge
- Walther suppose que le lecteur de QR échantillonne la zone centrale de la position de pixel attendue en se basant sur les blocs d’alignement
- Si le même masque est utilisé pour tous les pixels et que le centre du pixel tombe sur la frontière du masque, un petit déplacement peut faire dériver ensemble les points d’échantillonnage vers la zone de l’un des deux codes
- Le résultat est qu’une même image peut être lue comme deux codes QR différents selon son déplacement
- Walther précise lui-même que cette explication sur l’échantillonnage reste une hypothèse, et non le fruit d’une étude du fonctionnement réel des décodeurs
- Un utilisateur a indiqué qu’en fournissant directement le PNG au décodeur
zbar-tools, celui-ci ne détectait pas le code
Les différences créées par le masque et le décodeur
- Dans les expériences de Walther, le masque en damier donnait de meilleurs résultats que des rayures verticales ou diagonales
- L’utilisation du niveau maximal de correction d’erreurs semblait mieux fonctionner, même si des essais supplémentaires restent nécessaires
- La séparation diagonale est plus esthétique, mais le damier la surpasse en pratique
- Des écarts de fréquence de résultat ont aussi été signalés entre applications de scan et applications photo par défaut
- Un utilisateur a indiqué que l’application de scanner QR affichait plus souvent le lien Mastodon, tandis que l’application photo par défaut semblait pouvoir lire les deux
- Attie Grande a observé une variabilité également entre décodeurs logiciels
- Hadley a expliqué que le code ne se scannait pas lorsqu’il gardait le téléphone immobile, mais qu’il devenait lisible de façon stable pendant le mouvement, une fois l’appareil mis à bouger sous un autre angle
Expériences dérivées et outils publics
- Au cours de l’échange, Walther a présenté dualqrcode.com et le dépôt GitHub DualQRCode comme versions interactives
- xssfox a mentionné une approche consistant à rechercher des collisions proches afin de réduire le nombre de bits différents, en ajoutant que trouver en force brute 30 bits d’écart semblait assez simple
- Walther a testé l’idée de choisir des motifs de masque différents pour les deux codes QR afin de réduire leurs écarts, mais c’est le cas où les deux codes utilisent le même masque qui produisait le moins de différences
- Le proof of concept d’origine utilisait déjà le mask 6 choisi automatiquement par le générateur pour les deux codes, donc il n’y avait pas de gain supplémentaire dans ce cas
- Walther a expliqué avoir choisi volontairement deux domaines différents, car l’application photo d’iOS n’affiche que le domaine dans l’aperçu en temps réel et ne montre le contenu complet qu’après un tap
Couleurs, canal alpha et expérience à quatre codes
- Nemo Thorx a partagé une expérience où trois représentations de
42étaient chacune converties en code QR puis combinées dans les canaux RGB- le rouge contenait
6x9 - le vert contenait
XLII - le bleu contenait
Forty-two - il a ensuite été confirmé dans la discussion que le canal alpha contenait le code
㊷
- le rouge contenait
- Walther a indiqué qu’il avait compris le fonctionnement de cette image une fois le canal alpha ignoré
- Lorsque Pixel Dunn a voulu insérer plusieurs codes par mélange de couleurs, Walther a estimé que ce type de blending colorimétrique ne permettrait pas au décodeur de séparer quatre codes individuels, et que cela ne fonctionnerait donc pas
- Walther a dit avoir déjà réussi à intégrer 4 codes en utilisant des blocs d’alignement déplaçables et les quadrants de pixels
- En déplaçant très légèrement les cibles d’alignement, on peut focaliser sur d’autres quadrants des pixels
- Une méthode où deux ensembles de codes changeraient selon le fond transparent et le thème pourrait éventuellement être possible, mais l’iPhone de Walther ne reconnaissait ni la version sur fond blanc ni celle sur fond noir, et cela ne marchait qu’après application manuelle d’un traitement par seuillage
1 commentaires
Avis sur Hacker News
Il semble possible de mener une attaque où un écran dans un lieu public modifie légèrement un code QR en fonction des informations de l’utilisateur actuel, sans que cela paraisse très différent visuellement
Par exemple, on pourrait créer un code QR mélangé moitié-moitié, choisir une cible à partir d’entrées externes comme une évaluation de caractéristiques basée sur la caméra, puis ajuster subtilement les couleurs du code pour augmenter la probabilité qu’il soit reconnu dans le sens voulu
Parmi les usages malveillants possibles : montrer des formulaires de retour différents selon les groupes démographiques pour biaiser les résultats, favoriser les chances de gagner à un jeu-concours selon des caractéristiques identifiantes comme l’origine ethnique, l’âge ou l’apparence, ou encore envoyer seulement certaines personnes vers un autre réseau Wi‑Fi ou une autre page de paiement
Dans un environnement statique, l’effet est moindre, et je ne vois pas immédiatement d’attaque statique qui ne viserait qu’à soutirer un avantage à une partie des utilisateurs. Dans un éclairage public, la plupart des gens auraient sans doute du mal à remarquer qu’un code QR change dynamiquement
Le cas où la technique de piratage d’origine pourrait réellement servir me semble être celui où l’attaquant colle son propre code par-dessus un code QR légitime. Comme la lecture de l’un ou l’autre code serait un peu aléatoire, certains utilisateurs seraient envoyés vers la destination d’origine, ce qui pourrait retarder la détection, mais on ne sait pas si cela compenserait la baisse de trafic vers le lien malveillant
Il n’est même pas nécessaire d’aller jusqu’à quelque chose d’aussi sophistiqué que ce double code QR. Il suffit d’aller à un panneau de parking « payer avec votre téléphone », de coller son propre QR sur celui « scanner pour payer », puis d’attendre que des données de carte bancaire arrivent
Une autre méthode consisterait à utiliser une affiche qui n’est pas parfaitement plane. Si différents pixels ressortent légèrement en forme de pyramide et que chaque face est peinte différemment, le code QR pourrait être scanné différemment selon l’angle de vue
L’une des principales banques de Tbilissi permet de partager un numéro IBAN via un code QR. En théorie, on pourrait voler de l’argent avec ce type de technique, mais en pratique l’application bancaire affiche le nom du destinataire avant de finaliser le virement, entre autres garde-fous
Dans ma tête, ce type de contrôle pourrait aussi servir à forcer le choix d’une carte précise, donc j’ai d’abord pensé à des tours de magie
J’ai créé un site pour que l’on puisse tester directement : https://dualqrcode.com/
Comme Christian n’a pas publié de méthodologie exacte, j’ai ici fusionné deux codes QR en une seule image avec un motif de séparation en diagonale. Quand les motifs diffèrent au même emplacement, la cellule est divisée en diagonale : un côté représente le premier code QR, l’autre le second ; si les deux sont noirs ou blancs, la cellule est remplie d’une seule couleur
Grâce à la forte capacité de correction d’erreurs des codes QR, en particulier avec le niveau de correction « H », l’un ou l’autre des URL peut être lu selon l’angle de scan. En revanche, comme indiqué dans l’interface, le second URL est lu plus souvent
Sur iOS, un appui long sur l’image indique que cela mène vers github.com, alors que l’aperçu lui-même affiche Mastodon ; c’est ce qui m’a le plus intrigué
Cela semble vouloir dire que le code QR est analysé deux fois et produit des résultats différents. On pourrait s’en servir pour tromper certains utilisateurs, mais je ne sais pas combien de personnes consultent réellement l’URL du menu déroulant après un appui long
Du coup, j’ai déjà fait des choses absurdes comme envoyer une capture d’écran par AirDrop vers mon ordinateur portable pour la scanner avec l’appareil photo du téléphone, ou demander à un ami ou à un membre de ma famille de scanner le code affiché sur mon écran avec son téléphone
Mais j’ai appris aujourd’hui qu’il suffit d’effectuer un appui long sur un code QR dans une capture d’écran de la pellicule pour qu’il soit analysé immédiatement et que le lien s’ouvre. J’ai peut-être déjà essayé d’appuyer longuement sur une image par le passé, mais soit la fonctionnalité a été ajoutée ensuite, soit je ne l’avais jamais vraiment fait, soit j’appuyais sur la mauvaise partie du code QR. Quoi qu’il en soit, je suis très content d’apprendre que c’est possible
On pourrait probablement obtenir le même effet avec un code QR standard contenant des erreurs intentionnelles. Il suffirait de déterminer comment chacun corrige différemment les erreurs
On dirait une faille de bug bounty qui n’attend plus que quelqu’un la récupère
Cela fait penser à du code comme
if someCondition(getFoo()) then doSomethingWith(getFoo()), ou àdoSomethingWith(getFoo())suivi d’un appel àdoAnotherThingWith(getFoo()). Contrairement à une approche du typefoo := getFoo()où l’on récupère la valeur une fois pour la réutiliser, ce genre de chose laisse toujours une odeur de codeEn faisant défiler vers le haut depuis la position de départ, on peut voir la version lenticulaire
C’est extrêmement saisissant. Mon iPhone avait tendance à se verrouiller sur l’un des deux, et faire pivoter le téléphone aidait à partir vers l’un ou l’autre
À plusieurs reprises, les liens Mastodon et GitHub se sont même mis à clignoter en alternance
Si vous voulez essayer vous-même, vous pouvez utiliser un bout de code bricolé rapidement. Il suffit d’installer le package Python
qrcodeet d’exécuter le code ci-dessousOn obtient bien un double code QR avec
fooetbar, mais HN ne gère pas l’Unicode, et si on remplace par8ou0, mon téléphone ne le reconnaît pas, donc il est difficile de le coller tel quelCe serait génial pour une chasse au trésor
Les codes QR sont parfaits pour les abus, comme les URL raccourcies
Ce sont essentiellement des URL illisibles : impossible de savoir où elles mènent ni combien de redirections elles effectueront. C’est pour cela que je ne les utilise pas
Concept vraiment excellent. Si l’on se concentre sur l’objectif final, une autre approche serait aussi de mettre un commutateur au niveau de la destination URL
L’idée serait de rediriger vers des pages différentes selon l’aléatoire, les données utilisateur ou d’autres critères. Si vous voulez expérimenter ce genre de fonctionnalité et même faire de vrais tests sur autocollants, je travaille avec plusieurs entreprises SaaS et sur des projets d’étiquettes variables ; je peux donc partager des idées, imprimer des échantillons ou collaborer