1 points par GN⁺ 4 시간 전 | 1 commentaires | Partager sur WhatsApp
  • Un développeur a mené une expérience consistant à considérer le favicon, l’icône d’onglet du navigateur, comme un stockage de bytes par pixel, et à y placer un petit HTML dans les canaux RGB de l’image
  • L’encodage consiste à ajouter un en-tête de 4 bytes devant les bytes UTF-8 du HTML, puis à écrire chaque byte successivement dans les valeurs R, G et B des pixels
  • Le payload de démonstration fait 208 bytes, et 212 bytes avec l’en-tête ; 71 pixels stockant 3 bytes chacun, ainsi qu’un PNG 9×9, suffisaient donc
  • Pour la restauration, l’image du favicon est dessinée sur un canvas, puis JavaScript lit les données de pixels et réassemble les valeurs RGB en tableau de bytes avant de les décoder en HTML
  • La structure ne permet pas au site web de s’exécuter de manière autonome avec le seul favicon ; un bootstrap JavaScript séparé est nécessaire, ce qui en fait davantage une expérimentation aux limites qu’une approche pratique

Comment traiter un favicon comme un espace de stockage

  • Un favicon est une petite icône affichée dans l’onglet du navigateur, mais c’est en réalité un fichier image composé de pixels et de bytes
  • L’expérience part de la stéganographie, mais dans cette démo, l’objectif n’est pas de ressembler à une icône, plutôt d’utiliser l’image comme pur espace de stockage
  • La cible de stockage est un petit payload HTML
Website in a Favicon

Everything you're reading right now was decoded from favicon pixels.

  • La procédure d’encodage est simple
    • conversion du HTML en bytes UTF-8 avec TextEncoder
    • ajout, au début, d’un en-tête de 4 bytes contenant la longueur du payload
    • comme il peut rester des pixels inutilisés, l’en-tête de longueur permet d’identifier la fin réelle du payload
    • le premier byte est stocké dans le canal red du premier pixel, le deuxième dans green, le troisième dans blue
    • les pixels suivants sont remplis dans le même ordre, de sorte que l’intégralité du document HTML est encodée dans les valeurs de couleur
  • L’image résultante ressemble visuellement à du bruit

Taille et processus de restauration

  • La taille finale de la démo est très petite
    • payload : 208 bytes
    • total avec l’en-tête : 212 bytes
    • pixels nécessaires : 71 pixels
    • dimensions de l’image : 9×9 pixels
    • taille : 239 bytes
    • taux d’utilisation : 87% {p:87}
  • La restauration se fait uniquement avec les fonctionnalités du navigateur
    • chargement du favicon comme image
    • dessin de l’image sur un canvas
    • lecture de tous les pixels via la Canvas API
    • reconstruction d’un tableau de bytes à partir des valeurs RGB
    • lecture de la longueur du payload dans les 4 premiers bytes
    • extraction du payload et décodage en texte UTF-8
  • Sur le site de démonstration, un clic sur le bouton "Render Website" lit le favicon, restaure le HTML, puis remplace le contenu de la page

Limites et alternatives

  • La contrainte la plus importante est qu’un favicon ne peut pas, à lui seul, exécuter l’ensemble du site web
    • le favicon contient le contenu du site web
    • un petit chargeur JavaScript dédié au décodage est nécessaire en plus
    • sans JavaScript, le favicon n’est qu’un PNG contenant le contenu du site web
  • L’intérêt pratique est limité
    • la quantité de données stockable est très faible
    • la page doit être bootstrapée en JavaScript
    • il existe de bien meilleures façons de distribuer un petit document HTML
  • Parmi les alternatives : insérer directement du markup dans un favicon SVG, utiliser les chunks de commentaire tEXt, zTXt, iTXt d’un PNG, ou le format de fichier ico, qui peut contenir des icônes de plusieurs résolutions
  • Site de démo : https://www.timwehrle.de/labs/favicon-site/
  • Code d’implémentation : https://github.com/timwehrle/favicon

1 commentaires

 
GN⁺ 4 시간 전
Commentaires sur Hacker News
  • Au lieu de passer par des pixels, on pourrait simplement utiliser un favicon SVG, y stocker directement le balisage, puis l’extraire
    Il suffirait de mettre quelque chose comme hello HN! dans favicon.svg, de l’utiliser comme favicon SVG, puis de l’extraire et de l’injecter dans le corps du document

    • Plutôt que de se demander « pourquoi ne pas faire ça comme alternative », il vaut mieux y voir « une variante amusante ». Dans les deux cas, c’est une façon de jouer avec la technique par amusement, curiosité et esprit d’exploration, et l’approche consistant à stocker cela dans les pixels a un côté machine de Rube Goldberg très plaisant
    • C’est l’auteur de l’article, et oui, cette méthode est évidemment plus pratique. Mais je voulais que la charge utile « vive » dans les véritables données de pixels, et non comme un texte caché dans un fichier XML, d’où ce choix :)
    • Une regex, beurk. Il suffit de l’encoder correctement en XML dans le bon namespace, puis de le lire ainsi
      Sinon, on peut aussi servir directement le fichier SVG et y inclure du HTML embarqué. En théorie, on devrait pouvoir le définir puis l’utiliser, mais en pratique ni Firefox ni Chromium ne semblent bien le gérer dans un favicon, ce qui est dommage
    • Puisque c’est mon moulin à vent personnel, je me permets de signaler que [\s\S] peut s’écrire de manière plus courte et plus exacte avec [^]
    • Un SVG peut embarquer une image raster sous forme d’octets encodés en base64
      On peut donc empiler une couche supplémentaire d’expérimentation : un favicon en SVG, contenant un raster encodé, dont les octets contiennent eux-mêmes du HTML encodé. Au minimum, ça ferait une étape de CTF assez hallucinante
  • Bien sûr, ce n’est pas une idée nouvelle. Par exemple, quelqu’un a stocké deCSS dans un favicon en 2000
    https://web.archive.org/web/20010408040524if_/http://decss.z...
    L’extraction peut se faire avec dd bs=1 skip=2238 < favicon.ico

  • Cela ne veut pas dire qu’« il faut encore un petit bootstrap loader pour décoder l’image ». Avec un polyglot HTML/PNG, on peut tout faire tenir dans un seul fichier, et avec des formats plus récents comme WebP, on pourrait même obtenir de meilleurs taux de compression
    https://web.archive.org/web/20120801001616/http://daeken.com...

  • Si l’on redirige l’utilisateur vers plusieurs domaines, le cache des favicons peut aussi servir de stockage. Cela a déjà été proposé comme risque potentiel de fingerprinting[0], et si le navigateur réutilise naïvement ce cache même en mode privé, cela peut servir au pistage inter-profils
    [0]: https://www.schneier.com/blog/archives/2021/02/browser-track...

    • Ce n’était pas déjà corrigé, ou du moins corrigé dans la plupart des cas ?
    • Ma réaction instinctive en lisant l’article a été : « ça doit déjà être utilisé pour le fingerprinting ». Je me demande si les contre-mesures anti-fingerprinting prennent en compte la combinaison favicon + Canvas API
      Le lien vers le site de supercookie est malheureusement mort
  • Le PNG a des chunks de commentaire tEXt, zTXt, iTXt. On peut y fourrer autant de contenu qu’on veut dans un fichier image en apparence totalement banal. Bon, c’est un peu moins amusant, certes

  • Quel timing, c’est une coïncidence ? Il y a tout juste une heure, ou plutôt 30 minutes avant cet article, j’ai posté un site qui stocke un portefeuille d’actions dans l’URL + le favicon
    https://news.ycombinator.com/item?id=48606396

  • Cela correspond parfaitement à cette manière de penser : le moniteur est aussi un support de stockage, le clavier aussi, et les messages de forum aussi
    En introduisant au fil du temps des variations éditoriales dont Markov approuverait le style, on obtient une capacité de stockage assez importante. Et comme les commentaires sont parfois socialement intéressants, cela fait un support de stockage à double usage.
    Personne ne sait si la recette de gratin de poulet de quelqu’un n’est pas en réalité le handle d’un GUID soigneusement construit qui pointe, pour plaisanter, vers mille messages de forum différents. Je me demande si l’auteur connaît PoC||GTFO, car c’est clairement le genre de technique qu’on s’attend à trouver dans les profondeurs du livre sacré des Alchemist Owls

    • Du code dans le code. Des roues dans les roues
  • Le style, très haché et agressif, donnait clairement l’impression d’un texte généré par un LLM, et c’était très pénible à lire

    • Je m’étais plaint de ce style il y a quelques mois sur Medium. L’auteur de l’article m’avait répondu que c’était un style privilégié quand on s’attend à être lu sur un petit écran de smartphone. Ça se tient en partie. Je ne sais pas si cet article-là ou celui-ci a été généré par IA ou non
    • Vers le milieu, j’étais convaincu qu’à la fin l’article révélerait : « en fait, ce texte lui-même était stocké dans le favicon du site », ce qui aurait expliqué les phrases courtes et saccadées. Quand j’ai compris que non, j’ai été sincèrement déçu. C’était une occasion manquée
    • Moi, j’ai bien aimé cette façon d’écrire. J’écris parfois de manière similaire, et je n’ai jamais utilisé de LLM pour générer mes textes. J’ai même déjà écrit exactement comme ça au travail
      Pour moi, l’auteur essaie juste d’aller droit au but. Il semble savoir que quand il y a trop de texte, les gens se mettent à survoler
    • Pour une fois, je ne suis pas d’accord avec l’étiquette style généré par IA sur HN. Au pire, il a peut-être utilisé un LLM pour esquisser un brouillon, mais le résultat final paraît assez humain
      Il s’est trompé entre it’s/its, a fait de But. une phrase d’un seul mot, n’a pas écrit HTML en majuscules, et a mis « okayy » entre parenthèses. Ce n’est pas pour critiquer l’auteur, au contraire : j’ai trouvé agréable de voir ces petites imperfections qui composent un billet de blog
    • Le texte était prenant et agréable à lire
  • Ça m’a rappelé le real pixel coding d’Inigo : https://www.youtube.com/watch?v=FvS_DG8yIqQ
    C’est une intro de 256 octets réalisée en plaçant les pixels dans Photoshop puis en l’enregistrant comme exe

  • Fait amusant : n’importe quel SVG inline peut être utilisé comme favicon et laissé tel quel dans un document HTML
    Cela permet aussi d’utiliser directement un emoji comme favicon. Sur HN, les emojis ne s’affichent pas

    • À noter que si l’on veut utiliser des codes couleur #rrggbb ou des liens url(#id) de cette manière, il faut échapper # en %23. Sinon, ce sera analysé comme un fragment d’URL et le code SVG sera tronqué à cet endroit