- Backdoor
xzyang ditemukan pada Maret 2024 dapat berujung pada eksekusi kode jarak jauh di lingkungansshdyang 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 untuk5.6.0dan5.6.1, dan selama build membuat skrip shell serta file objek dari file pengujian.xzpalsu - Serangan memanfaatkan ifunc milik
glibcuntuk menjalankan kode saatliblzmadimuat, serta menargetkan lingkungan turunan Debian dan Fedora tempatsshdbergantung secara transitif padaliblzmamelaluilibsystemd - NixOS biasanya lebih memilih arsip sumber yang dibuat otomatis oleh GitHub, tetapi karena
xzberada pada tahap bootstrapnixpkgs, NixOS harus memercayai tarball maintainer untuk menghindari siklus dependensiautoconf - Pertahanan yang diusulkan adalah membangun ulang
xzdari sumber GitHub setelah bootstrap lalu membandingkannya dengan artefak tarball yang ada; ketika kondisinya diaktifkan, terlihat perbedaan ukuranliblzma.sodan penambahan simbol_get_cpuid
Cara backdoor xz disisipkan
xzadalah 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
sshsebesar 500 ms pada beberapa mesin Debian unstable, menelusurinya hinggaliblzma, lalu mengidentifikasi dan mendokumentasikan backdoor tersebut - Tujuan backdoor itu adalah membajak
sshagar 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 rilisxz5.6.0 dan 5.6.1 yang dibangun, ditandatangani, dan didistribusikan oleh Jia Tan - Beberapa file
.xzuntuk 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.m4tampak tidak berbahaya dan bahkan diberi komentar, tetapi sebenarnya menyembunyikan rantai perintah untuk mendekripsi dan menghapus obfuscation dari beberapa file pengujian.xzpalsu - Hasil dari proses ini ada dua
- Skrip shell yang dijalankan selama build
xz - File objek biner berbahaya
- Skrip shell yang dijalankan selama build
- Skrip shell yang dijalankan selama build memiliki dua peran
- Memeriksa kondisi eksekusi backdoor, seperti distribusi Linux tertentu, fitur
glibc, dan apakahsshterpasang - Memodifikasi objek normal
liblzma_la-crc64_fast.oagar menggunakan simbol_get_cpuiddari file objek backdoor
- Memeriksa kondisi eksekusi backdoor, seperti distribusi Linux tertentu, fitur
Analisis skrip xzdari 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
glibcadalah fitur untuk memilih salah satu dari beberapa implementasi fungsi yang sama pada saat dynamic loading, dan backdoorxzmenggunakannya sebagai jalur eksekusi kode berbahaya - Pada beberapa distribusi seperti Debian dan Fedora,
sshditautkan denganlibsystemduntuk dukungan notifikasisystemd, danlibsystemdkemudian ditautkan lagi denganliblzma- Dalam lingkungan ini,
sshdbergantung secara transitif padaliblzma
- Dalam lingkungan ini,
- Saat
sshddijalankan, dynamic loader memuatlibsystemddanliblzma, dan jika backdoor terpasang, kode berbahaya dijalankan saatliblzmadimuat - Backdoor membuat resolver ifunc memanggil simbol
_get_cpuidberbahaya, lalu memanipulasi GOT yang belum bersifat read-only untuk mengganti alamatRSA_public_decryptdengan 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
xzdari 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
- Ini adalah cara distribusi Linux awal yang lebih tua daripada
- 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
fetchFromGitHubjika memungkinkan, tetapi paketxzmengambil tarball maintainer yang diunggah manual melaluifetchurl - Alasannya adalah karena
xztermasuk dalam tahap bootstrapnixpkgs- Bootstrap adalah proses yang memungkinkan seluruh paket
nixpkgsdibangun ulang dari sekumpulan kecil seed binary stdenvadalah lingkungan kompilasi dasar yang digunakan paket lainstdenvbergantung padaxzsaat runtime, dan paket seperticoreutilsmembutuhkanxzuntuk mengekstrak arsip sumber.tar.xz
- Bootstrap adalah proses yang memungkinkan seluruh paket
- Untuk membangun
xzdari sumber GitHub diperlukanautoconfguna membuat skrip configure, tetapiautoconfjuga bergantung padaxz- Tarball yang disediakan maintainer sudah berisi skrip configure yang telah dibuat, sehingga siklus dependensi ini dapat diputus
- Karena itu, pada titik
xzdibangun dalam grafnixpkgs, 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
xzdapat 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
xzsekali lagi setelah bootstrap, kali ini menggunakan arsip sumber GitHub melaluifetchFromGitHub, lalu membandingkannya dengan artefakxzdari tahap bootstrap yang ada - Contoh implementasinya menaruh
after-bootstrap.nixdi bawahpkgs/tools/compression/xzdan membangunxz5.6.1 dari sumber GitHub- Tarball maintainer sudah berisi skrip configure, tetapi build dari sumber GitHub harus menjalankan
./autogen.shdengan menggunakanautoconf,libtool,automake, dan lainnya
- Tarball maintainer sudah berisi skrip configure, tetapi build dari sumber GitHub harus menjalankan
- Sebagai tahap perbandingan,
compareArtifactsditambahkan untuk membandingkanliblzma.sodi akhir build- Dalam contoh, hanya
liblzma.so, file yang dimodifikasi oleh backdoor, yang dibandingkan, tetapi ini dapat digeneralisasi ke semua artefak biner dan library
- Dalam contoh, hanya
- Pada revisi master normal, build
xz-after-bootstrapberhasil dan kedua artefak identik - Pada revisi
c53bbe3yang 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 binerliblzma.soterlihat
- Di NixOS, backdoor tidak aktif, dan salah satu alasannya adalah skrip instalasi memeriksa pengaturan variabel
- Saat kedua
liblzma.sodisimpan 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_cpuidadalah simbol yang didokumentasikan dalam berbagai laporan teknis tentang backdoorxz
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-bootstrapditambahkan 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 repositorinixpkgs - Metode ini membutuhkan asumsi bahwa paket target dapat direproduksi hingga tingkat bit
- Dari 2017 hingga 2023, 17 revisi
nixpkgs-unstabledijadikan sampel, dan non-fixed-output derivation daristdenvdibangun ulang dengannix-build --check - Pada semua revisi,
xzdapat direproduksi hingga tingkat bit - Pada 12 dari 17 revisi, ada 1–2 paket yang dapat dibangun tetapi tidak dapat direproduksi; misalnya
gccsecara konsisten tidak dapat direproduksi dari 2017 hingga 2021, danbashhingga 2019
- Dari 2017 hingga 2023, 17 revisi
- 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
xzyang tidak tepercaya pada tahap bootstrap tidak dapat mencemari buildxz-after-bootstrapsecara tidak langsung hingga artefaknya tampak identik - Serangan semacam itu bisa sangat kompleks, tetapi metode ini sendiri bergantung pada asumsi tersebut
- Diperlukan asumsi bahwa
- 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
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
Jika semua proses bisa dijalankan dengan hak akses terbatas dan bahkan tidak bisa mengakses
~/kecuali direktori yang diperlukan untuk tugasnya, maka misalnya paketpipberbahaya 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 biasaBelakangan 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
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
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
Build reproducible yang terverifikasi bisa membantu mencegah kasus seperti kompromi xz utils dan manipulasi SolarWinds Orion, dan itu sangat layak diupayakan
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
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
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
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
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