1 ポイント 投稿者 GN⁺ 4 시간 전 | 1件のコメント | WhatsAppで共有
  • 開発者は、ブラウザのタブアイコンである favicon をピクセル単位のバイト格納領域と見なし、小さなHTMLを画像のRGBチャネルに入れる実験を行った
  • エンコードは、HTMLの UTF-8バイト の先頭に4バイトの長さヘッダーを付け、各バイトをピクセルのR・G・B値へ順番に記録する方式
  • デモのペイロードは208バイトで、ヘッダー込みで212バイトだったため、3バイトずつ格納する71ピクセルと 9×9 PNG で十分だった
  • 復元は、favicon画像をcanvasに描画したあと、JavaScriptがピクセルデータを読み取り、RGB値を再びバイト配列に組み立ててHTMLとしてデコードする
  • faviconだけでウェブサイトが単独実行される構造ではなく、別途 bootstrap JavaScript が必要なため、実用性よりも境界的な実験に近い

faviconをストレージのように扱う方法

  • faviconはブラウザのタブに表示される小さなアイコンだが、実際にはピクセルとバイトで構成された 画像ファイル である
  • 実験の出発点はステガノグラフィーだったが、デモではアイコンらしく見せることより、純粋な保存領域として使うことに重点が置かれている
  • 保存対象は小さなHTMLペイロードである
Website in a Favicon

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

  • エンコード手順は単純
    • TextEncoder でHTMLを UTF-8バイト に変換する
    • ペイロード長を入れた 4バイトヘッダー を先頭に付ける
    • 余るピクセルが出る可能性があるため、長さヘッダーで実際のペイロード終端を判別する
    • 1バイト目は最初のピクセルのredチャネル、2バイト目はgreen、3バイト目はblueに保存される
    • 以降のピクセルも同じ順序で埋められ、HTML文書全体が色の値として入る
  • 結果の画像は見た目にはノイズのように見える

サイズと復元プロセス

  • デモの最終サイズは非常に小さい
    • ペイロード: 208 bytes
    • ヘッダー込み総量: 212 bytes
    • 必要なピクセル数: 71 pixels
    • 画像サイズ: 9×9 pixels
    • 容量: 239 bytes
    • 使用率: 87% {p:87}
  • 復元はブラウザ機能だけで処理される
    • faviconを画像としてロードする
    • 画像をcanvasに描画する
    • Canvas APIですべてのピクセルを読み取る
    • RGB値をバイト配列として再構成する
    • 先頭4バイトからペイロード長を読む
    • ペイロードを抽出し、UTF-8テキストとしてデコードする
  • デモサイトでは "Render Website" ボタンを押すとfaviconを読み込み、HTMLを復元してからページ内容を置き換える

制約と代替案

  • 最大の制約は、faviconがウェブサイト全体を単独では実行できないことにある
    • faviconにはウェブサイトの コンテンツ が入っている
    • デコード用の小さなJavaScriptローダーが別途必要
    • JavaScriptがなければ、faviconはウェブサイトの内容を含むPNGにすぎない
  • 実用性は低い
    • 保存できるデータ量が非常に小さい
    • ページはJavaScriptでブートストラップされる必要がある
    • 小さなHTML文書を配布する方法は他にももっとよいものが多い
  • 代替案としては、SVG faviconにmarkupを直接入れる方法、PNGの tEXtzTXtiTXt comment chunk を使う方法、複数解像度のアイコンを格納できる ico ファイル形式を使う方法がある
  • デモサイト: https://www.timwehrle.de/labs/favicon-site/
  • 実装コード: https://github.com/timwehrle/favicon

1件のコメント

 
GN⁺ 4 시간 전
Hacker News のコメント
  • ピクセルを経由せずに SVG favicon を使って、その中にマークアップを直接保存してから取り出せばいいのでは、と思った
    favicon.svghello HN! のような内容を入れ、SVG favicon として使ったあと、文書本文に抽出して貼り付ければよい

    • 「なぜ代替案としてやらないのか」よりも、「面白いバリエーションもある」と見るほうが適切だと思う。どちらも楽しさ・好奇心・探究のために技術で遊ぶやり方であり、ピクセルの中に保存するアプローチには ルーブ・ゴールドバーグ・マシン 的な面白さがある
    • 筆者だけど、もちろんこの方法のほうが実用的。ただ、ペイロードを XML ファイル内の隠しテキストではなく、実際の ピクセルデータ の中に「生きたまま」存在させたくてこうした :)
    • 正規表現だなんて、うっ。正しい名前空間で XML としてきちんとエンコードし、そのように読み込めばよい
      あるいは SVG ファイルをそのまま提供し、HTML を埋め込んで含めてもよい。理論上は定義してから使えるはずだが、実際には Firefox も Chromium も favicon の中ではきちんと処理しないようで残念
    • 個人的にこだわっている点として言うと、[\s\S] はもっと短く、しかも正確に [^] と書ける
    • SVG にはラスター画像を base64 エンコードされたバイト列 として埋め込める
      なので実験をさらに一段重ねて、favicon は SVG、その中にエンコードされたラスターがあり、そのバイト列の中に HTML がエンコードされている構造も可能。少なくとも気が遠くなるような CTF の段階にはなりそう
  • もちろん新しいアイデアではない。たとえば 2000 年には誰かが deCSS を favicon に保存していた
    https://web.archive.org/web/20010408040524if_/http://decss.z...
    抽出は dd bs=1 skip=2238 < favicon.ico で可能

  • 「画像をデコードするための小さなブートストラップローダーが依然として必要だ」という話ではない。HTML/PNG ポリグロット を使えば単一ファイルですべて処理でき、今なら WebP のような新しい形式で圧縮率もさらに良くできるかもしれない
    https://web.archive.org/web/20120801001616/http://daeken.com...

  • ユーザーを複数のドメインにリダイレクトすれば、favicon キャッシュ もストレージとして使える。潜在的な fingerprinting リスクとして提案されたことがあり[0]、ブラウザがシークレットモードでもキャッシュを安易に再利用するなら、ブラウザプロファイル間でのユーザー追跡に悪用されうる
    [0]: https://www.schneier.com/blog/archives/2021/02/browser-track...

    • これはすでに修正済み、あるいは大半は修正済みではなかったか?
    • 元記事を読んだ瞬間、反射的に「これは fingerprinting に使われていそうだ」と思った。anti-fingerprinting 対策が favicon と Canvas API の組み合わせまで考慮しているのか気になる
      supercookie サイトへのリンクは残念ながら死んでいる
  • PNG には tEXt, zTXt, iTXt コメントチャンクがある。見た目には完全に普通の画像ファイルのまま、好きなだけ内容を詰め込める。もちろん面白さは少し減るだろうが

  • これはタイミングの偶然? つい1時間前、正確にはこの記事の30分前に、私が作った 株式ポートフォリオを URL + favicon に保存するサイト を投稿した
    https://news.ycombinator.com/item?id=48606396

  • この考え方には本当によく合っている。モニターもストレージ だし、キーボードもストレージ、フォーラムの投稿もストレージだ
    時間をかけて編集に Markov が承認しそうな変形を加えれば、かなりの保存容量が得られる。しかもコメントはときどき社会的にも興味深いので、二重用途のストレージになる。
    誰かのチキンキャセロールのレシピが、実は巧妙に構成された GUID のハンドルで、冗談半分に言えば千個の異なるフォーラム投稿を指しているのかもしれないが、誰にもわからない。筆者が PoC||GTFO を知っているのか気になるが、これはまさに Alchemist Owls の聖典の奥深くにありそうな技法だ

    • コードの中のコード。車輪の中の車輪
  • 攻撃的に短く切る、明らかに LLM 生成 のように見える文体で、とても読みにくかった

    • 数か月前に Medium でこういう文体について不満を書いたことがある。その記事の著者は、小さなスマートフォン画面で読まれることを想定するなら好まれるスタイルだと答えていた。ある程度は筋が通っている。その記事やこの記事が AI 生成かどうかはわからない
    • 途中まで読んだとき、記事の最後に「実はこの記事自体がサイトの favicon に保存されていた」というオチが来て、この短くぶつ切りの文体を説明してくれるのだと確信していた。違うとわかって本当にがっかりした。逃したチャンスだった
    • 私はこの書き方が好きだった。私もときどき似たように書くし、自分の文章を生成するために LLM を使ったことはない。仕事でもまさにこんな書き方をしたことがある
      私には、筆者はただ要点にすぐ入りたいだけに見える。文章が多すぎると人は流し読みし始めるとわかっているのだと思う
    • 久しぶりに HN で AI 生成文体 という認定には同意しない。せいぜい LLM で下書きを作った可能性はあるが、最終結果はかなり人間らしく見える
      it’s/its を間違えていたし、But. を一語だけの文にしていたし、HTML を大文字で書いていなかったし、括弧内に “okayy” と書いていた。筆者を批判したいわけではなく、こうした小さな不完全さがブログ記事を形作っているのが見えて、むしろより楽しかった
    • 没入感があって楽しく読めた
  • Inigo の real pixel coding を思い出した: https://www.youtube.com/watch?v=FvS_DG8yIqQ
    Photoshop でピクセルを配置し、exe として保存して作った 256 バイトイントロだ

  • 面白い事実として、どんな インライン SVG でも favicon にでき、HTML 文書内にそのまま置いておける
    こうすると絵文字を favicon として直接使うことも可能。HN では絵文字は表示されない

    • 参考までに、こうするときに #rrggbb の色コードや url(#id) リンクを使いたいなら、#%23 にエスケープする必要がある。そうしないと URL fragment として解釈され、SVG コードがその地点で切れてしまう