1 puntos por GN⁺ 4 시간 전 | 1 comentarios | Compartir por WhatsApp
  • Un desarrollador trató el favicon, el ícono de la pestaña del navegador, como un almacén de bytes por píxel e hizo un experimento para meter un pequeño HTML en los canales RGB de una imagen
  • La codificación consiste en anteponer un encabezado de 4 bytes a los bytes UTF-8 del HTML y escribir cada byte en orden en los valores R, G y B de los píxeles
  • El payload de demostración es de 208 bytes y, con el encabezado, llega a 212 bytes, así que bastaron 71 píxeles guardando 3 bytes por píxel y un PNG de 9×9
  • La restauración se hace dibujando la imagen del favicon en un canvas; luego JavaScript lee los datos de píxeles y vuelve a ensamblar los valores RGB como un arreglo de bytes para decodificarlos a HTML
  • No es una estructura donde el sitio web se ejecute de forma autónoma solo con el favicon; hace falta un bootstrap JavaScript aparte, así que se parece más a un experimento de exploración de límites que a algo práctico

Cómo tratar un favicon como si fuera almacenamiento

  • Un favicon es un pequeño ícono que se muestra en la pestaña del navegador, pero en realidad es un archivo de imagen compuesto por píxeles y bytes
  • El punto de partida del experimento fue la esteganografía, pero en la demo el enfoque está más en usarlo como espacio de almacenamiento puro que en hacer que parezca un ícono
  • Lo que se guarda es un pequeño payload HTML
Website in a Favicon

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

  • El proceso de codificación es simple
    • Convierte el HTML a bytes UTF-8 con TextEncoder
    • Agrega al principio un encabezado de 4 bytes con la longitud del payload
    • Como pueden sobrar píxeles, el encabezado de longitud permite distinguir dónde termina el payload real
    • El primer byte se guarda en el canal red del primer píxel, el segundo byte en green y el tercero en blue
    • Después se rellenan los demás píxeles en el mismo orden hasta que todo el documento HTML queda representado como valores de color
  • La imagen resultante se ve visualmente como ruido

Tamaño y proceso de restauración

  • El tamaño final de la demo es muy pequeño
    • Payload: 208 bytes
    • Total con encabezado: 212 bytes
    • Píxeles necesarios: 71 pixels
    • Tamaño de imagen: 9×9 pixels
    • Tamaño de archivo: 239 bytes
    • Uso: 87% {p:87}
  • La restauración se resuelve solo con funciones del navegador
    • Carga el favicon como imagen
    • Dibuja la imagen en un canvas
    • Lee todos los píxeles con la Canvas API
    • Reconstruye un arreglo de bytes a partir de los valores RGB
    • Lee la longitud del payload desde los primeros 4 bytes
    • Extrae el payload y lo decodifica como texto UTF-8
  • En el sitio de demostración, al pulsar el botón "Render Website", se lee el favicon, se restaura el HTML y luego se reemplaza el contenido de la página

Límites y alternativas

  • La mayor limitación es que el favicon no puede ejecutar por sí solo todo el sitio web
    • El favicon contiene el contenido del sitio web
    • Se necesita aparte un pequeño cargador en JavaScript para decodificarlo
    • Sin JavaScript, el favicon no es más que un PNG con contenido de sitio web
  • Su utilidad práctica es baja
    • La cantidad de datos que se puede guardar es muy pequeña
    • La página tiene que arrancar con bootstrap mediante JavaScript
    • Hay muchas mejores formas de distribuir documentos HTML pequeños
  • Como alternativas, se mencionan incrustar el markup directamente en un favicon SVG, usar los comment chunks tEXt, zTXt, iTXt de PNG, o usar el formato de archivo ico, que puede contener íconos de varias resoluciones
  • Sitio de demostración: https://www.timwehrle.de/labs/favicon-site/
  • Código de implementación: https://github.com/timwehrle/favicon

1 comentarios

 
GN⁺ 4 시간 전
Comentarios de Hacker News
  • Me da la impresión de que, en vez de pasar por los píxeles, se podría usar un SVG favicon y guardar el marcado directamente dentro para luego extraerlo
    Podrías poner algo como hello HN! en favicon.svg, usarlo como SVG favicon y luego extraerlo y pegarlo en el cuerpo del documento

    • Más que preguntarse “por qué no hacerlo como alternativa”, creo que encaja mejor verlo como “también hay una variante interesante”. Ambas son formas de jugar con la tecnología por diversión, curiosidad y exploración, y el enfoque de guardarlo dentro de los píxeles tiene esa gracia de una máquina de Rube Goldberg
    • Soy el autor, y claro, este método es más práctico. Pero lo hice así porque quería que el payload “viviera” dentro de los datos reales de píxeles, no como texto oculto dentro de un archivo XML :)
    • ¿Regex? Uf. Solo hay que codificarlo bien como XML en el namespace correcto y leerlo de esa forma
      O también podrías servir el archivo SVG tal cual e incluir HTML embebido dentro. En teoría deberías poder definirlo y luego usarlo, pero por desgracia parece que ni Firefox ni Chromium lo procesan bien dentro de un favicon
    • Ya que personalmente esa es mi lucha contra molinos de viento: [\s\S] se puede escribir de forma más corta y precisa como [^]
    • SVG puede embeber una imagen rasterizada como bytes codificados en base64
      Así que podrías apilar el experimento una capa más: que el favicon sea un SVG, que dentro tenga un raster codificado y que dentro de esos bytes haya HTML codificado. Como mínimo, eso ya parece una etapa de CTF para perder la cordura
  • Claro que no es una idea nueva. Por ejemplo, en 2000 alguien guardó deCSS en un favicon
    https://web.archive.org/web/20010408040524if_/http://decss.z...
    Se puede extraer con dd bs=1 skip=2238 < favicon.ico

  • Tampoco es que “todavía haga falta un pequeño bootstrap loader para decodificar la imagen”. Con un HTML/PNG polyglot se puede hacer todo en un solo archivo, y hoy en día formatos más nuevos como WebP podrían dar incluso mejor compresión
    https://web.archive.org/web/20120801001616/http://daeken.com...

  • Si rediriges al usuario por varios dominios, también puedes usar la caché de favicon como almacenamiento. Se propuso como un posible riesgo de fingerprinting[0], y si el navegador reutiliza la caché de forma ingenua incluso en modo incógnito, se puede abusar para rastrear usuarios entre perfiles del navegador
    [0]: https://www.schneier.com/blog/archives/2021/02/browser-track...

    • ¿Eso no estaba ya arreglado, o al menos mayormente arreglado?
    • Apenas leí el post original pensé de inmediato, por instinto, “esto se va a usar para fingerprinting”. Me pregunto si las medidas anti-fingerprinting contemplan también la combinación de favicon con la Canvas API
      Por desgracia, el enlace al sitio del supercookie ya no funciona
  • PNG tiene chunks de comentarios tEXt, zTXt, iTXt. Puedes meterle todo el contenido que quieras a un archivo de imagen que por fuera parece totalmente normal. Claro, aunque quizá tenga un poco menos de gracia

  • ¿Será casualidad el timing? Justo hace 1 hora, o más exactamente 30 minutos antes de este post, publiqué un sitio para guardar mi portafolio de acciones en la URL + favicon
    https://news.ycombinator.com/item?id=48606396

  • Encaja muy bien con esta forma de pensar: el monitor también es almacenamiento, el teclado también es almacenamiento, y los posts de foros también son almacenamiento
    Si con el tiempo introduces variaciones en la edición que Markov aprobaría, aparece bastante capacidad de almacenamiento. Además, como los comentarios a veces también son socialmente interesantes, se vuelven almacenamiento de doble uso.
    Nadie sabe si la receta de casserole de pollo de alguien es en realidad el handle de un GUID cuidadosamente construido y, en broma, apunta a mil posts distintos en foros. Me pregunto si el autor conoce PoC||GTFO, porque esto definitivamente parece una técnica que encontrarías en lo más profundo del libro sagrado de los Alchemist Owls

    • Código dentro del código. Rueda dentro de rueda
  • El estilo de escritura, con cortes agresivos y muy marcados, me resultó muy difícil de leer porque parecía claramente generado por un LLM

    • Hace unos meses me quejé en Medium sobre este estilo. El autor de ese texto respondió que, si uno espera que se lea en la pantalla pequeña de un smartphone, es un estilo preferible. Hasta cierto punto tiene sentido. No sé si ese texto o este fueron generados por IA o no
    • A mitad del texto estaba convencido de que al final iba a venir un giro tipo “en realidad este mismo artículo estaba guardado en el favicon del sitio”, lo cual explicaría las frases cortas y entrecortadas. Cuando vi que no era así, me decepcioné de verdad. Fue una oportunidad perdida
    • A mí sí me gustó esta forma de escribir. Yo también escribo a veces de manera parecida y nunca he usado un LLM para generar mis textos. Incluso en el trabajo he escrito exactamente así
      A mí me parece que el autor simplemente quiere ir directo al punto. Da la impresión de que sabe que cuando hay demasiado texto la gente empieza a leer por encima
    • En mucho tiempo, esta es la primera vez en HN que no estoy de acuerdo con la etiqueta de estilo generado por IA. Como mucho, quizá haya usado un LLM para hacer un borrador, pero el resultado final se ve bastante humano
      Se equivocó con it’s/its, hizo de But. una oración de una sola palabra, no escribió HTML en mayúsculas y puso “okayy” entre paréntesis. No es por criticar al autor; al contrario, me gustó más ver esas pequeñas imperfecciones que forman parte de un post de blog
    • El texto fue inmersivo y agradable de leer
  • Me recordó al real pixel coding de Inigo: https://www.youtube.com/watch?v=FvS_DG8yIqQ
    Es una intro de 256 bytes hecha colocando píxeles en Photoshop y guardándola como exe

  • Dato curioso: cualquier SVG inline se puede usar como favicon y dejarlo tal cual dentro de un documento HTML
    Así también se pueden usar emojis directamente como favicon. En HN los emojis no se muestran

    • Ojo: si haces esto y quieres usar códigos de color #rrggbb o enlaces url(#id), tienes que escapar # como %23. Si no, se interpreta como fragment de URL y el código SVG se corta en ese punto