1 poin oleh GN⁺ 4 jam lalu | 1 komentar | Bagikan ke WhatsApp
  • Seorang pengembang melakukan eksperimen dengan melihat favicon, ikon tab browser, sebagai penyimpanan byte berbasis piksel, lalu menaruh HTML kecil ke dalam kanal RGB gambar
  • Proses encoding dilakukan dengan menambahkan header panjang 4 byte di depan byte UTF-8 HTML, lalu menulis setiap byte secara berurutan ke nilai R·G·B piksel
  • Payload demo berukuran 208 byte, dan menjadi 212 byte termasuk header, sehingga cukup dengan 71 piksel yang masing-masing menyimpan 3 byte serta PNG 9×9
  • Untuk memulihkan data, gambar favicon digambar ke canvas lalu JavaScript membaca data piksel dan menyusun kembali nilai RGB menjadi array byte untuk didekode sebagai HTML
  • Struktur ini tidak membuat situs web bisa berjalan mandiri hanya dengan favicon; tetap dibutuhkan bootstrap JavaScript terpisah, sehingga ini lebih merupakan eksperimen batas daripada sesuatu yang praktis

Cara memperlakukan favicon seperti penyimpanan

  • favicon adalah ikon kecil yang ditampilkan di tab browser, tetapi pada dasarnya merupakan berkas gambar yang tersusun dari piksel dan byte
  • Titik awal eksperimen ini adalah steganografi, tetapi pada demo fokusnya bukan membuatnya tampak seperti ikon, melainkan menggunakannya sebagai ruang penyimpanan murni
  • Yang disimpan adalah payload HTML kecil
Website in a Favicon

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

  • Prosedur encoding-nya sederhana
    • Menggunakan TextEncoder untuk mengubah HTML menjadi byte UTF-8
    • Menambahkan header 4 byte yang berisi panjang payload di bagian depan
    • Karena mungkin ada piksel yang tersisa, header panjang dipakai untuk menandai akhir payload yang sebenarnya
    • Byte pertama disimpan di kanal merah piksel pertama, byte kedua di hijau, dan byte ketiga di biru
    • Piksel berikutnya diisi dengan urutan yang sama sehingga seluruh dokumen HTML masuk ke dalam nilai warna
  • Gambar hasilnya secara visual tampak seperti noise

Ukuran dan proses pemulihan

  • Ukuran akhir demo sangat kecil
    • Payload: 208 bytes
    • Total termasuk header: 212 bytes
    • Piksel yang dibutuhkan: 71 pixels
    • Ukuran gambar: 9×9 pixels
    • Kapasitas: 239 bytes
    • Tingkat pemakaian: 87% {p:87}
  • Pemulihan dilakukan hanya dengan fitur browser
    • favicon dimuat sebagai gambar
    • gambar digambar ke canvas
    • semua piksel dibaca dengan Canvas API
    • nilai RGB disusun ulang menjadi array byte
    • panjang payload dibaca dari 4 byte pertama
    • payload diekstrak lalu didekode menjadi teks UTF-8
  • Di situs demo, saat tombol "Render Website" ditekan, favicon dibaca dan HTML dipulihkan lalu isi halaman diganti

Batasan dan alternatif

  • Kendala terbesar adalah favicon tidak bisa menjalankan seluruh situs web sendirian
    • favicon berisi konten situs web
    • loader JavaScript kecil untuk decoding tetap dibutuhkan secara terpisah
    • Tanpa JavaScript, favicon hanyalah PNG yang memuat konten situs web
  • Kegunaan praktisnya rendah
    • data yang bisa disimpan sangat sedikit
    • halaman harus di-bootstrap dengan JavaScript
    • ada banyak cara yang lebih baik untuk mendistribusikan dokumen HTML kecil
  • Alternatifnya antara lain memasukkan markup langsung ke SVG favicon, menggunakan comment chunk tEXt, zTXt, iTXt pada PNG, atau memakai format berkas ico yang dapat memuat ikon multi-resolusi
  • Situs demo: https://www.timwehrle.de/labs/favicon-site/
  • Kode implementasi: https://github.com/timwehrle/favicon

1 komentar

 
GN⁺ 4 jam lalu
Komentar Hacker News
  • Rasanya kita bisa saja tidak lewat piksel dan memakai SVG favicon, lalu menyimpan markup langsung di dalamnya dan mengekstraknya
    Cukup taruh isi seperti hello HN! di favicon.svg, pakai itu sebagai SVG favicon, lalu ekstrak dan tempelkan ke isi dokumen

    • Menurutku ini lebih tepat dilihat bukan sebagai “kenapa tidak dijadikan alternatif”, melainkan “ada variasi menarik juga”. Keduanya sama-sama cara bermain-main dengan teknologi demi kesenangan, rasa ingin tahu, dan eksplorasi, dan pendekatan menyimpan di dalam piksel punya keseruan seperti mesin Rube Goldberg
    • Saya penulisnya, dan ya, cara itu memang lebih praktis. Tapi saya ingin payload-nya “hidup” di dalam data piksel yang nyata, bukan sebagai teks tersembunyi di file XML, jadi saya melakukannya seperti ini :)
    • Regex? Aduh. Cukup enkode dengan benar sebagai XML dalam namespace yang tepat lalu baca begitu saja
      Atau sajikan file SVG apa adanya dan sertakan HTML sebagai embed. Secara teori seharusnya bisa didefinisikan lalu dipakai, tapi sayangnya di praktiknya baik Firefox maupun Chromium tampaknya tidak menanganinya dengan benar di dalam favicon
    • Secara pribadi, sebagai seseorang yang suka ngotot soal hal begini, [\s\S] bisa ditulis lebih singkat dan lebih akurat sebagai [^]
    • SVG bisa meng-embed gambar raster sebagai byte hasil enkode base64
      Jadi eksperimennya bisa ditumpuk satu lapis lagi: favicon-nya SVG, di dalamnya ada raster yang dienkode, dan di dalam byte itu ada HTML yang dienkode. Minimal ini terasa seperti level CTF yang bikin pusing
  • Tentu ini bukan ide baru. Misalnya, pada tahun 2000 seseorang menyimpan deCSS di favicon
    https://web.archive.org/web/20010408040524if_/http://decss.z...
    Ekstraksinya bisa dilakukan dengan dd bs=1 skip=2238 < favicon.ico

  • Bukan berarti “tetap dibutuhkan bootstrap loader kecil untuk mendekode gambar”. Dengan HTML/PNG polyglot, semuanya bisa ditangani dalam satu file, dan sekarang kompresinya bahkan bisa lebih baik dengan format baru seperti WebP
    https://web.archive.org/web/20120801001616/http://daeken.com...

  • Jika pengguna diarahkan ulang ke beberapa domain, cache favicon juga bisa dipakai sebagai penyimpanan. Ini pernah diusulkan sebagai potensi risiko fingerprinting[0], dan jika browser secara naif memakai ulang cache bahkan dalam mode penyamaran, ini bisa disalahgunakan untuk melacak pengguna antar profil browser
    [0]: https://www.schneier.com/blog/archives/2021/02/browser-track...

    • Bukankah ini sudah diperbaiki, atau setidaknya sebagian besar sudah diperbaiki?
    • Begitu membaca posting aslinya, insting pertamaku langsung berkata, “ini pasti bisa dipakai untuk fingerprinting”. Aku penasaran apakah langkah anti-fingerprinting juga mempertimbangkan kombinasi favicon dan Canvas API
      Sayangnya tautan ke situs supercookie itu sudah mati
  • PNG punya chunk komentar tEXt, zTXt, iTXt. Kita bisa menyelipkan sebanyak apa pun isi yang diinginkan ke dalam file gambar yang tampak sepenuhnya normal. Tentu saja, unsur serunya mungkin jadi agak berkurang

  • Apakah waktunya cuma kebetulan? Baru satu jam lalu, tepatnya 30 menit sebelum posting ini, saya mengunggah situs yang menyimpan portofolio saham ke URL + favicon yang saya buat
    https://news.ycombinator.com/item?id=48606396

  • Ini benar-benar cocok dengan cara berpikir seperti ini: monitor juga penyimpanan, keyboard juga penyimpanan, dan posting forum juga penyimpanan
    Jika seiring waktu penyuntingan diberi variasi yang mungkin disetujui Markov, kapasitas penyimpanannya bisa lumayan besar. Selain itu, komentar kadang juga menarik secara sosial, jadi ini menjadi penyimpanan dengan fungsi ganda.
    Tidak ada yang tahu apakah resep chicken casserole seseorang sebenarnya adalah handle dari GUID yang disusun dengan rumit, dan secara bercanda menunjuk ke seribu posting forum yang berbeda. Aku penasaran apakah penulisnya tahu PoC||GTFO, karena ini jelas teknik yang terasa seperti ditemukan jauh di dalam kitab suci milik Alchemist Owls

    • Kode di dalam kode. Roda di dalam roda
  • Gaya tulisannya yang terpotong-potong secara agresif dan jelas terlihat seperti hasil LLM membuatnya sangat sulit dibaca

    • Beberapa bulan lalu saya pernah mengeluhkan gaya seperti ini di Medium. Penulis artikel itu menjawab bahwa ini adalah gaya yang disukai jika diasumsikan akan dibaca di layar smartphone kecil. Ada benarnya juga. Saya tidak tahu apakah artikel itu atau artikel ini dibuat AI atau bukan
    • Saat membaca sekitar pertengahan, saya yakin di akhir tulisan akan ada twist bahwa “sebenarnya tulisan ini sendiri disimpan di favicon situs”, yang akan menjelaskan kalimat-kalimat pendek dan terputus-putus itu. Ketika sadar ternyata tidak, saya benar-benar kecewa. Itu kesempatan yang terlewat
    • Saya justru suka cara penulisan ini. Saya juga kadang menulis mirip begini, dan saya belum pernah memakai LLM untuk menghasilkan tulisan saya. Di kantor pun saya pernah menulis persis seperti ini
      Buat saya, penulisnya cuma terlihat ingin langsung ke intinya. Sepertinya dia tahu kalau tulisannya terlalu banyak, orang akan mulai sekadar memindai cepat
    • Sudah lama saya tidak setuju dengan cap gaya tulisan hasil AI di HN. Paling-paling mungkin draft awalnya dibuat dengan LLM, tetapi hasil akhirnya terlihat cukup manusiawi
      it’s/its tertukar, But. dijadikan kalimat satu kata, HTML tidak ditulis dengan huruf besar, dan ada “okayy” di dalam tanda kurung. Bukan bermaksud mengkritik penulisnya; justru saya lebih menikmati tulisan blog seperti ini karena terlihat tersusun dari ketidaksempurnaan kecil semacam itu
    • Tulisannya terasa imersif dan menyenangkan untuk dibaca
  • Ini mengingatkan saya pada real pixel coding milik Inigo: https://www.youtube.com/watch?v=FvS_DG8yIqQ
    Sebuah intro 256-byte yang dibuat dengan menata piksel di Photoshop lalu menyimpannya sebagai exe

  • Fakta menarik: SVG inline apa pun bisa dipakai sebagai favicon dan dibiarkan apa adanya di dalam dokumen HTML
    Dengan begini, emoji pun bisa langsung dipakai sebagai favicon. Di HN, emoji tidak ditampilkan

    • Sekadar catatan, kalau melakukan ini dan ingin memakai kode warna #rrggbb atau tautan url(#id), maka # harus di-escape menjadi %23. Kalau tidak, itu akan diparse sebagai fragmen URL dan kode SVG akan terpotong di titik itu