1 poin oleh GN⁺ 2025-03-24 | 1 komentar | Bagikan ke WhatsApp
  • Backdoor xz yang ditemukan pada Maret 2024 dapat berujung pada eksekusi kode jarak jauh di lingkungan sshd yang terdampak, dan kasus NixOS menunjukkan bahwa build yang dapat direproduksi dapat mengungkap manipulasi rantai pasok secara mekanis
  • Komponen berbahaya tidak tersembunyi di seluruh repositori Git xz, melainkan di tarball rilis yang disediakan maintainer untuk 5.6.0 dan 5.6.1, dan selama build membuat skrip shell serta file objek dari file pengujian .xz palsu
  • Serangan memanfaatkan ifunc milik glibc untuk menjalankan kode saat liblzma dimuat, serta menargetkan lingkungan turunan Debian dan Fedora tempat sshd bergantung secara transitif pada liblzma melalui libsystemd
  • NixOS biasanya lebih memilih arsip sumber yang dibuat otomatis oleh GitHub, tetapi karena xz berada pada tahap bootstrap nixpkgs, NixOS harus memercayai tarball maintainer untuk menghindari siklus dependensi autoconf
  • Pertahanan yang diusulkan adalah membangun ulang xz dari sumber GitHub setelah bootstrap lalu membandingkannya dengan artefak tarball yang ada; ketika kondisinya diaktifkan, terlihat perbedaan ukuran liblzma.so dan penambahan simbol _get_cpuid

Cara backdoor xz disisipkan

  • xz adalah perangkat lunak kompresi dan dekompresi yang sering digunakan saat mengekstrak tarball sumber di jalur inti distribusi Linux
  • Pada Maret 2024 ditemukan backdoor di xz, dan maintainer berbahaya Jia Tan memperoleh kepercayaan selama sekitar 3 tahun serta mendapatkan hak push ke repositori, lalu menyisipkan kode yang diobfuscate sedikit demi sedikit di antara kontribusi yang sah
  • Andres Freund menyelidiki penurunan kinerja ssh sebesar 500 ms pada beberapa mesin Debian unstable, menelusurinya hingga liblzma, lalu mengidentifikasi dan mendokumentasikan backdoor tersebut
  • Tujuan backdoor itu adalah membajak ssh agar saat login dengan kunci RSA tertentu, penyerang dapat menjalankan perintah arbitrer di mesin korban

Tarball berbahaya dan objek yang dibuat saat build

  • Komponen berbahaya tidak langsung berada di seluruh kode repositori Git xz, melainkan disertakan dalam tarball rilis xz 5.6.0 dan 5.6.1 yang dibangun, ditandatangani, dan didistribusikan oleh Jia Tan
  • Beberapa file .xz untuk pengujian di dalam repositori Git menyembunyikan kode mesin, dan tarball rilis menambahkan perubahan yang disamarkan untuk mengekstraknya
  • Secara khusus, perubahan pada m4/build-to-host.m4 tampak tidak berbahaya dan bahkan diberi komentar, tetapi sebenarnya menyembunyikan rantai perintah untuk mendekripsi dan menghapus obfuscation dari beberapa file pengujian .xz palsu
  • Hasil dari proses ini ada dua
    • Skrip shell yang dijalankan selama build xz
    • File objek biner berbahaya
  • Skrip shell yang dijalankan selama build memiliki dua peran
    • Memeriksa kondisi eksekusi backdoor, seperti distribusi Linux tertentu, fitur glibc, dan apakah ssh terpasang
    • Memodifikasi objek normal liblzma_la-crc64_fast.o agar menggunakan simbol _get_cpuid dari file objek backdoor
  • Analisis skrip xz dari Russ Cox membahas secara detail proses pembuatan resource berbahaya selama build

Pembajakan ifunc yang mengarah ke sshd

  • Pada program yang ditautkan secara dinamis, dynamic loader memuat shared library ke memori saat runtime dan mengisi alamat simbol ke Global Offset Table(GOT)
  • ifunc milik glibc adalah fitur untuk memilih salah satu dari beberapa implementasi fungsi yang sama pada saat dynamic loading, dan backdoor xz menggunakannya sebagai jalur eksekusi kode berbahaya
  • Pada beberapa distribusi seperti Debian dan Fedora, ssh ditautkan dengan libsystemd untuk dukungan notifikasi systemd, dan libsystemd kemudian ditautkan lagi dengan liblzma
    • Dalam lingkungan ini, sshd bergantung secara transitif pada liblzma
  • Saat sshd dijalankan, dynamic loader memuat libsystemd dan liblzma, dan jika backdoor terpasang, kode berbahaya dijalankan saat liblzma dimuat
  • Backdoor membuat resolver ifunc memanggil simbol _get_cpuid berbahaya, lalu memanipulasi GOT yang belum bersifat read-only untuk mengganti alamat RSA_public_decrypt dengan fungsi berbahaya
  • Analisis terperinci Securelist ini serta tulisan riset yang merangkum vektor serangan dan mitigasinya dapat dijadikan referensi

Sumber tepercaya dan batasan bootstrap NixOS

  • Serangan ini dapat berdampak karena banyak distribusi membangun xz dari tarball yang disediakan maintainer, bukan dari sumber asli di Git forge
  • Alur kerja tarball memiliki alasan historis dan praktis
    • Ini adalah cara distribusi Linux awal yang lebih tua daripada git
    • Menyimpan kondisi sumber pada saat rilis sebagai arsip yang lengkap
    • Dapat mengurangi beban build dengan menyertakan artefak antara seperti manpage dan skrip configure
    • Memberikan efisiensi ruang penyimpanan melalui kompresi
  • Dari sudut pandang keamanan, jika secara teknis memungkinkan, build harus dilakukan dari sumber yang diautentikasi oleh pihak paling tepercaya
    • Untuk proyek yang dikembangkan di GitHub, arsip yang dibuat otomatis oleh GitHub untuk setiap rilis dapat digunakan
    • Logika yang sama dapat diterapkan pada platform pihak ketiga tepercaya seperti Codeberg, SourceHut, dan GitLab
  • NixOS menggunakan model manajemen paket fungsional, dan paket mendefinisikan resep build sebagai ekspresi Nix
  • Maintainer NixOS memiliki budaya menggunakan arsip sumber yang dibuat otomatis oleh GitHub melalui fetchFromGitHub jika memungkinkan, tetapi paket xz mengambil tarball maintainer yang diunggah manual melalui fetchurl
  • Alasannya adalah karena xz termasuk dalam tahap bootstrap nixpkgs
    • Bootstrap adalah proses yang memungkinkan seluruh paket nixpkgs dibangun ulang dari sekumpulan kecil seed binary
    • stdenv adalah lingkungan kompilasi dasar yang digunakan paket lain
    • stdenv bergantung pada xz saat runtime, dan paket seperti coreutils membutuhkan xz untuk mengekstrak arsip sumber .tar.xz
  • Untuk membangun xz dari sumber GitHub diperlukan autoconf guna membuat skrip configure, tetapi autoconf juga bergantung pada xz
    • Tarball yang disediakan maintainer sudah berisi skrip configure yang telah dibuat, sehingga siklus dependensi ini dapat diputus
    • Karena itu, pada titik xz dibangun dalam graf nixpkgs, sulit menggunakan arsip sumber GitHub dan tarball maintainer harus dipercaya

Membandingkan konvergensi artefak, bukan membandingkan sumber

  • Membandingkan apakah tarball maintainer dan tarball sumber GitHub identik terlihat seperti pendekatan yang alami, tetapi dalam praktiknya kurang cocok
  • Daniel Stenberg menjelaskan bahwa perbedaan tarball rilis dari sumber adalah sebuah fitur
    • Artefak antara seperti manpage dan skrip configure dapat disertakan dalam tarball
    • Ini sangat berguna ketika distribusi ingin menghindari dependensi autoconf
  • Dari perspektif keamanan rantai pasok, fleksibilitas semacam ini berubah menjadi beban untuk memercayai maintainer agar bertindak jujur
  • Build yang dapat direproduksi adalah sifat ketika dua build dalam kondisi yang sama menghasilkan artefak yang identik hingga tingkat bit
  • Kelompok reproducible-builds bertujuan membuat sebanyak mungkin paket dapat direproduksi, dan Reproducible Builds: Increasing the Integrity of Software Supply Chains membahasnya sebagai properti yang meningkatkan kepercayaan dalam distribusi artefak biner
  • Pendekatan untuk membuat proses pembuatan tarball itu sendiri dapat direproduksi telah diadopsi oleh proyek PostgreSQL
    • Pengguna dapat memverifikasi secara independen bahwa tarball maintainer dibuat secara jujur dari sumber asli
    • Namun karena harus diimplementasikan oleh maintainer proyek upstream, adopsinya di komunitas FOSS bisa lambat

Prosedur deteksi yang diusulkan di NixOS

  • Jika xz dapat direproduksi hingga tingkat bit dan tarball maintainer tidak memuat perubahan yang memengaruhi proses build, build dari tarball GitHub dan build dari tarball maintainer seharusnya menghasilkan artefak yang sama
  • Metode yang diusulkan adalah membangun xz sekali lagi setelah bootstrap, kali ini menggunakan arsip sumber GitHub melalui fetchFromGitHub, lalu membandingkannya dengan artefak xz dari tahap bootstrap yang ada
  • Contoh implementasinya menaruh after-bootstrap.nix di bawah pkgs/tools/compression/xz dan membangun xz 5.6.1 dari sumber GitHub
    • Tarball maintainer sudah berisi skrip configure, tetapi build dari sumber GitHub harus menjalankan ./autogen.sh dengan menggunakan autoconf, libtool, automake, dan lainnya
  • Sebagai tahap perbandingan, compareArtifacts ditambahkan untuk membandingkan liblzma.so di akhir build
    • Dalam contoh, hanya liblzma.so, file yang dimodifikasi oleh backdoor, yang dibandingkan, tetapi ini dapat digeneralisasi ke semua artefak biner dan library
  • Pada revisi master normal, build xz-after-bootstrap berhasil dan kedua artefak identik
  • Pada revisi c53bbe3 yang memuat backdoor, awalnya keduanya tampak identik
    • Di NixOS, backdoor tidak aktif, dan salah satu alasannya adalah skrip instalasi memeriksa pengaturan variabel RPM_ARCH
    • Setelah kondisi diaktifkan dengan menetapkan env.RPM_ARCH = true;, perbedaan biner liblzma.so terlihat
  • Saat kedua liblzma.so disimpan dan dibandingkan, artefak yang memuat backdoor berukuran 258 KB, sedangkan artefak build dari sumber GitHub setelah bootstrap berukuran 210 KB, dengan selisih sekitar 48 KB
  • Ketika simbol dibandingkan dengan nm, ditemukan penambahan _cpuid, _get_cpuid, dan __tls_get_addr@GLIBC_2.3; _get_cpuid adalah simbol yang didokumentasikan dalam berbagai laporan teknis tentang backdoor xz

Cara penerapan dan keterbatasan

  • Perlindungan yang diusulkan diterapkan pada semua paket yang dibangun pada tahap bootstrap dan tidak menggunakan arsip sumber tepercaya
  • Jika paket *-after-bootstrap ditambahkan ke channel blocker, kegagalan build dapat menjadi alarm besar yang membutuhkan intervensi maintainer
  • Sebagai proof of concept untuk kasus xz, sebuah pull request dibuka di repositori nixpkgs
  • Metode ini membutuhkan asumsi bahwa paket target dapat direproduksi hingga tingkat bit
    • Dari 2017 hingga 2023, 17 revisi nixpkgs-unstable dijadikan sampel, dan non-fixed-output derivation dari stdenv dibangun ulang dengan nix-build --check
    • Pada semua revisi, xz dapat direproduksi hingga tingkat bit
    • Pada 12 dari 17 revisi, ada 1–2 paket yang dapat dibangun tetapi tidak dapat direproduksi; misalnya gcc secara konsisten tidak dapat direproduksi dari 2017 hingga 2021, dan bash hingga 2019
  • Metode ini tidak dapat diterapkan ke semua paket stdenv, tetapi dalam jangka panjang dapat diaktifkan secara selektif untuk paket dengan reproduksibilitas yang baik
  • Masalah trusting trust dari Ken Thompson tetap menjadi batasan teoretis metode ini
    • Diperlukan asumsi bahwa xz yang tidak tepercaya pada tahap bootstrap tidak dapat mencemari build xz-after-bootstrap secara tidak langsung hingga artefaknya tampak identik
    • Serangan semacam itu bisa sangat kompleks, tetapi metode ini sendiri bergantung pada asumsi tersebut
  • Metode deteksi ini hanya mendeteksi ketika perubahan tarball memengaruhi artefak akhir
    • Karena executable NixOS tidak memuat backdoor, jika kondisinya tidak diaktifkan secara terpisah, backdoor dalam kasus ini tidak akan ditemukan

1 komentar

 
GN⁺ 2025-03-24
Pendapat Hacker News
  • Perlu dicatat bahwa NixOS dan build yang reproducible tidak mendeteksi backdoor xz. Pada kenyataannya, NixOS juga mendistribusikan build xz berbahaya kepada pengguna, hanya saja malware itu tidak berjalan karena tidak menargetkan NixOS
    Pengembang NixOS juga mengatakan, “Saat backdoor itu diungkap, kami terkejut mengetahui bahwa versi xz berbahaya telah didistribusikan kepada pengguna kami.” Seperti biasa, teori dan kenyataan berbeda, dan yang memungkinkan xz bukanlah kelemahan teknis melainkan kerentanan manusia di dunia nyata. Komunitas sering kali sulit mengakui bahwa masalah seperti ini tidak selalu bisa ditambal hanya dengan perangkat lunak yang lebih baik

    • Konfigurasi deklaratif Nix cukup berguna untuk meningkatkan ketahanan terhadap serangan dalam berbagai cara, tetapi masih banyak potensi yang belum dimanfaatkan. Secara pribadi, saya paling ingin menerapkan container sekali pakai yang terperinci, dan Guix sudah memiliki fitur seperti ini
      Jika semua proses bisa dijalankan dengan hak akses terbatas dan bahkan tidak bisa mengakses ~/ kecuali direktori yang diperlukan untuk tugasnya, maka misalnya paket pip berbahaya tidak akan bisa mencuri kunci SSH. Meski begitu, saya kira alasan backdoor xz tidak berjalan di NixOS adalah karena struktur filesystem non-FHS NixOS yang tidak biasa
    • Meski begitu, tulisan ini bagus. NixOS mengusung solusi teknis untuk mencegah artefak build yang terpisah dari source code, yaitu artefak yang tidak reproducible, dan backdoor xz justru bersembunyi di dalam artefak build
    • Betul. Judulnya terkesan seperti berarti pendekatan Nix mungkin telah mendeteksi backdoor itu, padahal sebenarnya tulisan ini lebih mendekati usulan tentang bagaimana Nix bisa diubah agar dapat mendeteksi backdoor semacam itu
    • Saya senang tulisan ini menekankan bahwa build yang reproducible tidak benar-benar menangkap backdoor xz lebih dulu daripada jalur penemuan lainnya
      Belakangan ini, realitas yang benar-benar terjadi sering diremehkan jika tidak cocok dengan perasaan atau nilai pribadi orang tentang realitas objektif. Saya punya nilai pribadi, tetapi saya tidak menganggap kenyataan nyata kurang penting daripada perasaan saya tentangnya. Seperti ungkapan lama favorit, perbedaan antara teori dan kenyataan adalah bahwa dalam teori keduanya sama, tetapi dalam kenyataan tidak demikian. Saya berharap kesadaran bahwa build reproducible NixOS bisa saja menangkap serangan xz tetapi ternyata tidak, akan mendorong kemajuan untuk menganalisis build semacam itu dan menemukan serangan lain lebih cepat di masa depan
    • Alasannya agak lucu. Bootstrap NixOS mengunduh source code, dan source itu adalah tarball yang dikompresi dengan xz
  • Rasanya penulis terlalu terpaku pada cara kejadian ini berlangsung secara kebetulan kali ini. Kasus Jia Tan hanyalah satu sampel, jadi menganggap hanya cara itulah yang mungkin terjadi adalah pandangan yang sempit
    Sangat mudah membayangkan banyak skenario lain di mana pertahanan yang diusulkan di sini tidak akan berhasil. Bahkan sebagai pengguna Nix, saya menilai kecil kemungkinan NixOS akan menangkap ini. Faktanya, memang tidak tertangkap. Tadi memang disebutkan bahwa lain kali bisa terjadi dengan cara berbeda, tetapi tetap bodoh jika percaya begitu saja pada Nix tanpa bukti

  • NixOS sebenarnya tidak terlalu relevan di sini. Backdoor xz secara spesifik menargetkan Red Hat dan Debian
    Dengan logika yang sama, mengatakan bahwa backdoor xz tidak memengaruhi Windows juga sama relevannya. Ironisnya, backdoor ini justru ditemukan oleh seorang karyawan Microsoft, dan poin ini sering diabaikan

    • NixOS atau Guix yang sedikit ditingkatkan akan bisa mendeteksi backdoor ini secara otomatis saat masuk ke repositori. Jadi ini tetap relevan
  • Tulisan itu mengatakan distribusi seharusnya mengambil source code langsung dari sistem kontrol versi, misalnya Github, alih-alih dari tarball instalasi tradisional
    Tapi saya tidak begitu paham apa yang diselesaikan oleh ini. Bukankah maintainer jahat cukup menambahkan gumpalan biner langsung ke repositori source code? Penulis tampaknya menganggap Github dapat dipercaya seolah memverifikasi kode, padahal tentu saja Github tidak melakukan verifikasi seperti itu

    • Yang diselesaikan pendekatan ini adalah masalah bahwa yang “ditinjau” dan “source code yang dipakai untuk membangun perangkat lunak” sering kali berbeda
      Build reproducible yang terverifikasi bisa membantu mencegah kasus seperti kompromi xz utils dan manipulasi SolarWinds Orion, dan itu sangat layak diupayakan
    • Kritik itu agak kurang tepat. Jika Anda build dari source, Anda dan semua orang bisa memeriksa source tersebut, tetapi jika Anda build dari tarball yang disediakan, proses autoconf akan mengubah berkas sehingga hasilnya pada dasarnya berbeda saat dibandingkan dengan source asli
      Jika Anda mengunduh biner dari rilis Github lalu menjalankannya, satu-satunya pilihan adalah sepenuhnya memercayai maintainer. Nix hanya melakukan itu untuk paket closed-source
  • Argumennya bergantung pada fakta bahwa maintainer XZ menyembunyikan kode berbahaya di dalam tarball yang tidak di-commit ke Git
    Penulis menunjukkan bahwa Nix dapat dikonfigurasi agar membuat tarball dari Git lalu memasukkannya ke dalam build biner. Tetapi saya tidak paham mengapa ini harus menjadi fitur yang memerlukan Nix atau NixOS. Sistem build apa pun, termasuk yang dipakai untuk hal-hal yang masuk ke RPM atau Deb, bisa dikonfigurasi untuk membuat tarball sebagai langkah antara. Faktanya, Debian sudah lama mengerjakan build reproducible sebagai tujuan penting. https://wiki.debian.org/ReproducibleBuilds

    • Tulisan itu memang mengutip proyek reproducible-builds di bagian “Leveraging bitwise reproducibility”. Inti tulisannya ada dua
      Pertama, proses build NixOS tidak dapat melakukan build source lengkap untuk xz karena xz dibutuhkan terlalu awal dalam bootstrap. Kedua, tulisan itu mengusulkan penyesuaian pada nixpkgs untuk secara otomatis mendeteksi apakah dependensi nixpkgs yang diperlukan di awal bootstrap telah dikompromikan. Ekosistem lain tentu juga bisa mencoba build source lengkap untuk menemukan ketidaksesuaian. Inti tulisannya adalah bahwa nixpkgs saat ini belum bisa melakukan itu
  • Jika ingin fokus pada kasus yang bisa dicegah NixOS, seharusnya melihat insiden CrowdStrike. Fakta bahwa jika konfigurasi hari ini tidak berjalan Anda bisa boot ke konfigurasi kemarin saja sudah akan mengurangi sebagian besar dampaknya

    • Tetapi itu masalah di sisi Windows yang tidak punya fleksibilitas boot seperti itu. Ubuntu dengan ZFS juga bisa melakukannya
  • Jika memakai framework yang dipercaya, kita aman sampai framework itu sendiri diserang. Backdoor xz mungkin memang bisa ditemukan, tetapi itu tidak dirancang dengan tujuan agar berjalan di ekosistem Nix
    Suatu hari nanti jika pengembang inti Nix ternyata mata-mata atau terjadi situasi serupa, serangan yang menargetkan ekosistem Nix juga akan muncul. Saya harap tidak ada yang menjawab seolah-olah Nix pada dasarnya aman. Sampai-sampai rasanya kalau dalam 1~2 tahun ke depan Nix berhasil diserang, saya ingin mendatangi orang-orang dan membuat mereka mengakui bahwa mereka salah

    • Standarnya, dulu maupun nanti, bukan keamanan absolut. Itu standar mustahil yang tidak bisa dipenuhi apa pun. Meski begitu, adalah fakta objektif bahwa perangkat lunak saat ini secara umum lebih aman dibanding 30 tahun lalu
      Klaim yang lebih kuat adalah “Nix lebih sulit dan lebih mahal untuk diserang dibanding sistem build tradisional.” Jadi, kalau nanti ada yang menemukan cara murah untuk menyerang Nix, datanglah saat itu. Sampai sebelum itu, pada tingkat teknis, pernyataan bahwa Nix lebih sulit diserang daripada sistem alternatif setidaknya masuk akal, dan kemungkinan besar memang benar
    • Backdoor itu tidak menargetkan Nix, tetapi agar tidak terekspos, ia juga harus tidak menimbulkan kecurigaan selama dibangun di Nix
  • NixOS memang sedikit lebih maju, tetapi sebagian besar distro lain juga mengompilasi semuanya dari source, memverifikasi secara kriptografis bahwa source yang dipakai tidak dimanipulasi, dan memiliki dependensi versi yang ditentukan antar paket. Debian juga memiliki reproducible builds
    Masalahnya adalah sistem build tidak menghapus object file yang sudah dikompilasi sebelumnya sebelum membangun dari source. Bahkan kalau itu diperbaiki, jika tidak ada yang memeriksa source code, backdoor tetap bisa ditambahkan sebanyak yang diinginkan, dan baik NixOS maupun distro lain tidak bisa mencegahnya

  • Analisis teknisnya sangat bagus, tetapi judulnya salah dan menyesatkan. Mungkin bisa dibilang “secara teknis benar”, tetapi bahkan dalam penafsiran paling baik pun itu lebih dekat ke makna bahwa backdoor telah ditanamkan
    Ini menunjukkan dengan jelas perlunya alat pengelola build yang melampaui lapisan union filesystem. Misalnya, perlu ada pelacakan dan penegakan agar pengujian tidak bisa mencemari artefak hasil build. Diperlukan graf pelacakan kausal tentang bagaimana file memengaruhi file lain selama proses build, lalu graf itu dibuat secara eksplisit, kemudian diterapkan atau perbedaannya terhadap graf pelacakan sebelumnya dilaporkan

  • Betul. Menyembunyikan backdoor pasti akan menjadi jauh lebih sulit. Tetapi itu masih sangat jauh dari mustahil
    Jika mau, Anda selalu bisa menyembunyikan backdoor di dalam source code. Hanya saja, dibutuhkan lebih banyak usaha agar itu tampak seperti bug yang masuk akal, dan kemungkinan terdeteksinya juga menjadi lebih tinggi