back
109 comments
Instead of going via pixels, why not use a SVG favicon and directly store markup inside it and extract it?

Use this favicon.svg:

    <svg xmlns="http://www.w3.org/2000/svg">
    <circle cx="50%" cy="50%" r="50%" fill="orange"/>
    <p>hello HN!</p>
    </svg>
use this in your <head> to use a svg favicon:

    <link id="favicon" rel="icon" href="favicon.svg" type="image/svg+xml">
finally, use this in your <body> to extract it and add it to your document body:

    <script>
    fetch(favicon.href).then(r => r.text()).then(t => document.body.innerHTML += t.match(/<p[\s\S]*p>/)[0]);
    </script>
"why not alternative", would be better framed as, "here's a fun variation" — because both approaches are just playing around with technology, for fun / curiosity / exploration. Storing in the pixels is a fun approach, resulting in something Rube Goldberg-esque.
Hey, yeah, I wrote the article. This (of course) would be more practical. Thanks for pointing it out. I wanted the payload to "live" in actual pixel data rather than hidden text inside an XML file. That’s why I went this way :)
Regular expressions? Ugh. Encode it properly as XML in the correct namespace, load it so, and take it from that.

Or just serve the SVG file and use <foreignObject> to embed the HTML, and include <link rel="icon" href=""> inside it. In theory you should be able to define a <view id="icon"> and use <link rel="icon" href="#icon">, but in practice neither Firefox nor Chromium seems to be handling that properly in a favicon, which is disappointing.

Just because it's my windmill to tilt at: `[\s\S]` can be written shorter and more precisely as `[^]`.
An SVG can embed raster images: base64 encoded bytes.

So you could layer this experiment: favicon is svg, that contains encoded raster, whose bytes are encoded html.

At the very least it would make a mindboggling CTF step.

  <svg xmlns="http://www.w3.org/2000/svg">
    <circle cx="50%" cy="50%" r="50%" fill="orange"/>
    <p>hello HN!</p>
    </svg>
You can use the favicon cache as storage too, by redirecting users across domains. It's been proposed as a potential fingerprinting risk[0], and if a browser naively reuses the cache for incognito mode, it could be used to track users across browser profiles.

[0]: https://www.schneier.com/blog/archives/2021/02/browser-track...

My thoughts instinctively went to "this has to be being used for fingerprinting" when I read OPs blog. Are anti fingerprinting measures taking into account the use of the canvas api with favicons?

The link to the supercookie site is dead unfortunately.

Wasn't this fixed or mostly fixed?
> You still need a tiny bootstrap loader to decode the image.

Nope, you can do it all in a single file with an html/png polyglot (and nowadays you can get better compression ratios with newer formats like webp).

https://web.archive.org/web/20120801001616/http://daeken.com...

You can even make the file compatible with ZIP (and PDF) on top of that, see https://github.com/gildas-lormeau/Polyglot-HTML-ZIP-PNG/raw/... (and https://github.com/gildas-lormeau/Polyglot-HTML-ZIP-PNG)
PNG has comment chunks tEXt, zTXt, and iTXt. You can have a completely normal image whose file is stuffed with as much content as you want. That is less fun, I suppose.
Is this timing coincidence? I just submitted 1h (30 mins before this) ago a website I just made about storing your stock porfolio in a URL + favicon!

https://news.ycombinator.com/item?id=48606396

I found the agressively staccato, clearly LLM-generated content extremely difficult to read.
Oh, I am so aligned with this mentality:

    A monitor is storage.

    A keyboard is storage.
Forum posts are storage. Markov-approved tweaks in an edit, over time, certainly enough for quite a lot of storage. Dual-use storage to boot, since .. you know .. sometimes the comments are socially interesting.

Best thing is, nobody really knows if their chicken casserole recipe isn't just a handle to a carefully constructed GUID pointing across to .. lets say, for humor .. a thousand different forum postings ...

I do have to wonder if the author is familiar with PoC||GTFO, for this is certainly a technique one will find deep within the depths of the Alchemist Owls' holy tomes...

Fun Fact: You can use any inline SVG for a favicon and keep it right in the HTML document.

This also allows you to use an emoji directly as a favicon, like so:

  <link
    rel="icon"
    type="image/svg+xml"
    href="data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'><text y='.9em' font-size='90'>(your emoji here)</text></svg>"
  />
(HN isn't showing the emoji)
I'd love to see you try serving the exact same file for both but the trick is that you need to return different Content-Type headers depending on what is requested. When the browser requests /favicon from a navigation event it will use Accept: text/html etc, you return the file with Content-Type: text/html and inside the response you have a <link rel="favicon" href="/favicon" type="img/png"> literally the same resource but the browser will now likely fetch with Accept: image/... and you could return the same file with Content-Type: image/png and the same resource will get used for both. Unless the browser caches the response, I feel like this would work.

If you don't control the headers of your webserver (eg GitHub Pages) I would settle for a symlink favicon.png that just links back to favicon.html which I think would trick the server into returning different Content-Types.

Cool! Here is a GH repo demonstrating unbounded favicons I made 11 years ago - it crashes some browsers - wanna guess how long it took each one to fix it :D https://github.com/benjamingr/favicon-bug
That reminded me of Inigo's "real pixel coding" https://www.youtube.com/watch?v=FvS_DG8yIqQ

A 256b intro coded by placing pixels in photoshop and saving into an exe.

I played with this once hoping the browser wouldn't care what the file was.

The plan came from an experiment from long ago where I put 1x1 images at the end on my pages, the images loaded from websites my page linked to. Preloading the assets made those pages load much faster. Sadly it also broke pages that served "hot linking images not allowed" text on images.

The new plan was to have a javascript or css file called favicon.ico so that the browser would load it at the same time the html was requested. Then one wouldn't have to wait for the html to be parsed for the second round trip to happen.

Sadly it didn't work.

Love it. Did you see the old effort to store the page in the url? https://github.com/jstrieb/urlpages
I'd imagine the (aggressive) caching of the favicon by browsers makes it a challenge, but you could generate the favicon dynamically, then have JS extract the sequentially. Basically streaming arbitraily large content to a webpage via favicons. Via blocks of 239 bytes.

It may be a fun, novel way to proxy webpages that are otherwise blocked. Though, i guess, the service rendering the favicons can just as easily be blocked then.

Not a new idea of course. For example, back in 2000, someone stored deCSS in a favicon

https://web.archive.org/web/20010408040524if_/http://decss.z...

To extract

   dd bs=1 skip=2238 < favicon.ico
> The length header is important because the image itself may contain unused pixels at the end. If there's no length value, there's no way to know where the real payload stops.

Not really, can’t you just pad with 0 bytes and stop reading when you encounter one that’s not part of the current Unicode codepoint?

How long before someone ports DOOM into a favicon? ^_^

(For the technical gurus here, would that even be possible?)

Does't work for me. It rendered some garbage:

:f3=Ygbukte!in"c"Hbviann:1h3> =n= " Exgtyvhkle znt%pfsdafipg thfivlmu "vas dcdpeed hrondbvjbno"rixfls, ;.q>

I use Helium on Linux with Polish locale.

Have an index.html that's also (byte-to-byte equal) served as favicon.ico. If that page "works" and the favicon doesn't show garbage, it is a website stored in a favicon (by my standards).
Would have been more fun if the blogpost was rendered from the favicon.
This is one of those projects that's completely impractical but makes the web more interesting. I love seeing people explore weird constraints just to see what's possible.
Painful read.

Related interesting project: https://github.com/EtherDream/web2img

Pretty cool tbh!!! Would have loved seeing the decoder code!!!

It's also pretty interesting to think how an attacker could exploit images on his behalf. Never thought that would be a way!!!

Thanks!

Hmm this is cool but what are the practical use cases?

It didn’t load first time round on my browser (Brave) without disabling its prevent tracking feature…

I would have used a minimal service worker to unpack the web data and present it as if it were just a normal page being loaded.
Honestly it didn't interest me, but I do remember from back in the days full websites rendered by a browser from... Empty files. https://mathiasbynens.be/notes/css-without-html
I personally won't do things this way, but this is really cool and I could see the applications already.
You can literally just use the file itself as the favicon. There is no need to over complicate it.

cp index.html favicon.png

Any real usage scenarios for this? I mean, can it be used as anti-filter or whatever things.
Very cool. I wonder is it possible to make a simple game with also leveraging the webassembly?
Wait 'til the author discovers that you can use ping (ICMP) to transfer data, too! :)
The browser already asks for the favicon on every page. Might as well put it to work.
A neat improvement would be to make the decoder into a bookmarklet. This would avoid the overhead of serving the script. Of course you would rely on the user having the bookmarklet installed, but when you serve HTML you also rely on the user having a web browser installed.
also https://pong-in-a-favicon.franzai.com/ for further favicon (mis)use
Fascinating concept! Thanks for sharing this!
Bravo Maestro! Wonderful performance! =)
very cool and interesting after reading just the title I wrongly assumed this would be about svg
Surprised that a minimal "website" only requires a small image = few pixels = few bytes to store it? Um, ok.
Is it cake? Game for devs.
looks good