Ken Thompson Hack (1984)
Ken Thompson menguraikan metode untuk merusak biner kompiler (dan perangkat lunak terkompilasi lainnya, seperti skrip login pada sistem * nix) pada tahun 1984. Saya ingin tahu apakah kompilasi modern telah mengatasi cacat keamanan ini atau tidak.
Deskripsi Singkat:
Tulis ulang kode kompiler yang berisi 2 kelemahan:
- Ketika mengkompilasi binernya sendiri, kompiler harus mengkompilasi kekurangan ini
- Ketika mengkompilasi beberapa kode yang dipilih sebelumnya (fungsi login) itu harus mengkompilasi beberapa backdoor sewenang-wenang
Dengan demikian, kompiler bekerja secara normal - ketika ia mengkompilasi skrip login atau sejenisnya, ia dapat membuat backdoor keamanan, dan ketika ia mengkompilasi versi yang lebih baru dari dirinya sendiri di masa depan, ia menyimpan kekurangan sebelumnya - dan kekurangan tersebut hanya akan ada di kompiler biner jadi sangat sulit dideteksi.
Pertanyaan:
Saya tidak dapat menemukan jawaban untuk ini di web:
- Bagaimana ini berhubungan dengan kompilasi just-in-time?
- Apakah fungsi seperti program yang menangani login pada sistem * nix dikompilasi ketika dijalankan?
- Apakah ini masih merupakan ancaman yang sah, atau adakah perkembangan keamanan kompilasi sejak 1984 yang mencegah hal ini menjadi masalah yang signifikan?
- Apakah ini mempengaruhi semua bahasa?
Mengapa saya ingin tahu?
Saya menemukan ini saat melakukan pekerjaan rumah, dan itu tampak menarik tetapi saya tidak memiliki latar belakang untuk memahami secara konkret apakah ini masalah saat ini, atau masalah yang diselesaikan.
Jawaban:
Peretasan ini harus dipahami dalam konteks. Itu diterbitkan pada suatu waktu dan dalam budaya di mana Unix berjalan pada semua jenis perangkat keras yang berbeda adalah sistem yang dominan.
Apa yang membuat serangan itu begitu menakutkan adalah bahwa kompiler C adalah bagian utama dari perangkat lunak untuk sistem ini. Hampir semua yang ada di sistem melalui kompiler ketika pertama kali diinstal (distribusi biner jarang terjadi karena perangkat kerasnya yang heterogen). Semua orang menyusun hal-hal sepanjang waktu. Orang-orang secara teratur memeriksa kode sumber (mereka sering harus membuat penyesuaian untuk membuatnya dikompilasi sama sekali), sehingga memiliki kompiler menyuntikkan backdoors tampaknya menjadi semacam skenario "kejahatan sempurna" di mana Anda tidak dapat ditangkap.
Saat ini, perangkat keras jauh lebih kompatibel dan oleh karena itu penyusun memiliki peran yang jauh lebih kecil dalam operasi sistem sehari-hari. Kompiler yang dikompromikan bukan skenario yang paling menakutkan lagi - rootkit dan BIOS yang dikompromikan bahkan lebih sulit untuk dideteksi dan dihilangkan.
sumber
Tujuan dari pidato itu bukan untuk menyoroti kerentanan yang perlu ditangani, atau bahkan untuk mengusulkan kerentanan teoretis yang perlu kita waspadai.
Tujuannya adalah, ketika menyangkut keamanan, kami ingin tidak harus mempercayai siapa pun, tapi sayangnya itu tidak mungkin. Anda selalu harus mempercayai seseorang (karena itu judulnya: "Reflections On Trusting Trust")
Bahkan jika Anda adalah tipe paranoid yang mengenkripsi hard drive desktop-nya dan menolak untuk menjalankan perangkat lunak apa pun yang tidak Anda kompilasi sendiri, Anda masih perlu mempercayai sistem operasi Anda. Dan bahkan jika Anda mengkompilasi sistem operasi sendiri, Anda masih perlu mempercayai kompiler yang Anda gunakan. Dan bahkan jika Anda mengkompilasi compiler Anda sendiri, Anda masih perlu percaya bahwa compiler! Dan itu bahkan tidak menyebutkan produsen perangkat keras!
Anda tidak bisa pergi dengan tidak percaya pada siapa pun . Itulah poin yang dia coba sampaikan.
sumber
Tidak
Serangan itu, seperti yang dijelaskan pada awalnya, tidak pernah menjadi ancaman. Sementara kompiler secara teoritis bisa melakukan ini, sebenarnya melakukan serangan akan membutuhkan pemrograman kompiler untuk
Ini mencakup mencari tahu bagaimana kompiler bekerja dari kode sumbernya, agar dapat memodifikasinya tanpa kerusakan.
Misalnya, bayangkan bahwa format penautan menyimpan panjang data atau offset kode mesin yang dikompilasi di suatu tempat di executable. Kompiler harus mencari tahu sendiri mana yang perlu diperbarui, dan di mana, saat memasukkan muatan eksploitasi. Versi selanjutnya dari kompiler (versi tidak berbahaya) dapat mengubah format ini secara sewenang-wenang, sehingga kode exploit akan secara efektif perlu memahami konsep-konsep ini.
Ini adalah pemrograman tingkat tinggi yang diarahkan sendiri, masalah AI yang sulit (terakhir saya periksa, teknologi canggih ini menghasilkan kode yang secara praktis ditentukan oleh tipenya). Lihatlah: beberapa manusia bahkan dapat melakukan ini; Anda harus mempelajari bahasa pemrograman dan memahami basis kode terlebih dahulu.
Bahkan jika masalah AI diselesaikan, orang akan melihat jika kompilasi hasil kompilasi kecil mereka dalam biner dengan perpustakaan AI besar yang terhubung ke dalamnya.
Serangan analog: kepercayaan bootstrap
Namun, generalisasi serangan itu relevan. Masalah dasarnya adalah bahwa rantai kepercayaan Anda harus dimulai di suatu tempat, dan di banyak domain asalnya dapat menumbangkan seluruh rantai dengan cara yang sulit untuk dideteksi.
Contoh yang bisa dengan mudah ditarik dalam kehidupan nyata
Sistem operasi Anda, misalnya Ubuntu Linux, memastikan keamanan (integritas) pembaruan dengan memeriksa paket pembaruan yang diunduh terhadap kunci penandatanganan repositori (menggunakan kriptografi kunci publik). Tetapi ini hanya menjamin keaslian pembaruan jika Anda dapat membuktikan bahwa kunci masuk dimiliki oleh sumber yang sah.
Dari mana Anda mendapatkan kunci masuk? Ketika Anda pertama kali mengunduh distribusi sistem operasi.
Anda harus percaya bahwa sumber rantai kepercayaan Anda, kunci penandatanganan ini, tidak jahat.
Siapa pun yang dapat MITM koneksi Internet antara Anda dan server unduh Ubuntu — ini bisa berupa ISP Anda, pemerintah yang mengontrol akses Internet (misalnya China), atau penyedia hosting Ubuntu — dapat membajak proses ini:
Sejak saat itu, Anda akan mendapatkan pembaruan Anda dengan aman dari server penyerang. Pembaruan dijalankan sebagai root, sehingga penyerang memiliki kontrol penuh.
Anda dapat mencegah serangan dengan memastikan yang asli otentik. Tetapi ini mengharuskan Anda untuk memvalidasi gambar CD yang diunduh menggunakan hash ( hanya sedikit orang yang melakukan ini ) —dan hash itu sendiri harus diunduh dengan aman, misalnya melalui HTTPS. Dan jika penyerang Anda dapat menambahkan sertifikat di komputer Anda (umum di lingkungan perusahaan) atau mengendalikan otoritas sertifikat (misalnya Cina), bahkan HTTPS tidak memberikan perlindungan.
sumber
Pertama, writeup favorit saya untuk hack ini disebut Strange Loops .
Peretasan khusus ini tentunya (*) dapat dilakukan hari ini di salah satu proyek OS open source utama, terutama Linux, * BSD, dan sejenisnya. Saya berharap ini akan bekerja hampir identik. Misalnya, Anda mengunduh salinan FreeBSD yang memiliki kompiler yang dieksploitasi untuk memodifikasi openssh. Sejak saat itu, setiap kali Anda memutakhirkan openssh atau kompiler berdasarkan sumber, Anda akan melanjutkan masalahnya. Dengan asumsi penyerang telah mengeksploitasi sistem yang digunakan untuk mengemas FreeBSD di tempat pertama (kemungkinan, karena gambar itu sendiri rusak, atau penyerang sebenarnya adalah pembuat paket), maka setiap kali sistem membangun kembali binari FreeBSD, itu akan menginjeksi kembali masalah. Ada banyak cara agar serangan ini gagal, tetapi mereka pada dasarnya tidak berbeda dari bagaimana serangan Ken bisa gagal (**). Dunia benar-benar tidak banyak berubah.
Tentu saja, serangan serupa dapat dengan mudah (atau lebih mudah) disuntikkan oleh pemiliknya ke dalam sistem seperti Java, iOS SDK, Windows, atau sistem lainnya. Beberapa jenis kelemahan keamanan bahkan dapat direkayasa ke dalam perangkat keras (khususnya yang melemahkan generasi nomor acak).
(*) Tetapi dengan "tentu saja" maksud saya "sebagai prioritas." Haruskah Anda berharap bahwa lubang semacam ini ada di sistem tertentu? Tidak. Saya akan menganggapnya sangat tidak mungkin karena berbagai alasan praktis. Seiring waktu, seiring perubahan kode dan perubahan, kemungkinan peretasan semacam ini akan menyebabkan peningkatan bug aneh. Dan itu meningkatkan kemungkinan bahwa itu akan ditemukan. Ruang belakang yang kurang cerdik akan membutuhkan konspirasi untuk dipertahankan. Tentu saja kita tahu fakta bahwa backdoor "lawful intercept" telah dipasang di berbagai sistem telekomunikasi dan jaringan, sehingga dalam banyak kasus peretasan rumit semacam ini tidak diperlukan. Peretasan diinstal secara terbuka.
Jadi selalu, pertahanan dalam.
(**) Menganggap serangan Ken pernah benar-benar ada. Dia baru saja membahas bagaimana itu bisa dilakukan. Dia tidak mengatakan dia benar-benar melakukannya sejauh yang saya tahu.
sumber
Apakah ini mempengaruhi semua bahasa?
Serangan ini terutama memengaruhi bahasa yang hosting-sendiri. Itu adalah bahasa di mana kompiler ditulis dalam bahasa itu sendiri. C, Squeak Smalltalk, dan juru bahasa Python Python akan terpengaruh oleh ini. Perl, JavaScript, dan juru bahasa CPython Python tidak mau.
Bagaimana ini berhubungan dengan kompilasi just-in-time?
Tidak banyak. Ini adalah sifat self-hosting dari kompiler yang memungkinkan hack untuk disembunyikan. Saya tidak tahu ada kompiler JIT self-hosting. (Mungkin LLVM?)
Apakah fungsi seperti program yang menangani login pada sistem * nix dikompilasi ketika dijalankan?
Tidak biasanya. Tetapi pertanyaannya bukan kapan dikompilasi, tetapi oleh kompiler mana . Jika program login dikompilasi oleh kompiler ternoda, itu akan ternoda. Jika dikompilasi oleh kompiler bersih, itu akan bersih.
Apakah ini masih merupakan ancaman yang sah, atau adakah perkembangan keamanan kompilasi sejak 1984 yang mencegah hal ini menjadi masalah yang signifikan?
Ini masih merupakan ancaman teoretis, tetapi sangat tidak mungkin.
Satu hal yang dapat Anda lakukan untuk mengurangi itu adalah dengan menggunakan beberapa kompiler. Sebagai contoh, Kompiler LLVM yang, yang disusun sendiri oleh GCC tidak akan melewati pintu belakang. Demikian pula, GCC yang disusun oleh LLVM tidak akan melewati pintu belakang. Jadi, jika Anda khawatir tentang serangan semacam ini, maka Anda bisa mengkompilasi kompiler Anda dengan jenis kompiler lain. Itu berarti bahwa peretas jahat (di vendor OS Anda?) Harus mencemari kedua kompiler untuk saling mengenali; Masalah yang jauh lebih sulit.
sumber
Ada peluang teoretis untuk ini terjadi. Namun, ada cara untuk memeriksa apakah kompiler tertentu (dengan kode sumber yang tersedia) telah dikompromikan, melalui kompilasi ganda David A. Wheeler's Diverse .
Pada dasarnya, gunakan kedua kompiler yang dicurigai dan kompiler lain yang dikembangkan secara independen untuk mengkompilasi sumber dari kompiler yang dicurigai. Ini memberi Anda SC sc dan SC T . Sekarang, kompilasi sumber yang dicurigai menggunakan kedua binari ini. Jika biner yang dihasilkan identik (dengan pengecualian berbagai hal yang mungkin berbeda secara sah, seperti berbagai cap waktu), kompiler tersangka sebenarnya tidak menyalahgunakan kepercayaan.
sumber
Sebagai serangan spesifik, itu adalah ancaman yang sama besarnya dengan yang pernah ada, yang hampir tidak ada ancaman sama sekali.
Tidak yakin apa yang Anda maksud dengan itu. Apakah JITter kebal terhadap ini? Tidak. Apakah lebih rentan? Tidak juga. Sebagai pengembang, aplikasi ANDA lebih rentan hanya karena Anda tidak dapat memvalidasi bahwa itu belum dilakukan. Perhatikan bahwa aplikasi Anda yang belum dikembangkan pada dasarnya kebal terhadap ini dan semua variasi praktis, Anda hanya perlu khawatir tentang kompiler yang lebih baru dari kode Anda.
Itu tidak terlalu relevan.
Tidak ada keamanan kompilasi yang nyata, dan tidak bisa. Itu benar-benar inti pembicaraannya, bahwa pada titik tertentu Anda harus memercayai seseorang.
Iya. Pada dasarnya, pada suatu waktu atau lain, instruksi Anda harus diubah menjadi sesuatu yang komputer lakukan, dan terjemahan itu dapat dilakukan dengan salah.
sumber
David Wheeler memiliki artikel bagus: http://www.dwheeler.com/trusting-trust/
Saya, saya lebih khawatir tentang serangan perangkat keras. Saya pikir kita membutuhkan toolchain desain VLSI sepenuhnya dengan kode sumber FLOSS, yang dapat kita modifikasi dan kompilasi sendiri, yang memungkinkan kita membangun mikroprosesor yang tidak memiliki backdoors yang dimasukkan oleh alat. Alat-alat tersebut juga harus memungkinkan kita memahami tujuan dari setiap transistor pada chip. Kemudian kita bisa membuka sampel chip yang sudah jadi dan memeriksanya dengan mikroskop, memastikan mereka memiliki sirkuit yang sama seperti yang dikatakan alat.
sumber
Sistem di mana pengguna akhir memiliki akses ke kode sumber adalah yang mana Anda harus menyembunyikan jenis serangan ini. Itu akan menjadi sistem open source di dunia saat ini. Masalahnya adalah bahwa meskipun ada ketergantungan pada satu kompiler untuk semua sistem Linux, serangan itu harus masuk ke server build untuk semua distribusi Linux utama. Karena mereka tidak mengunduh binari kompiler secara langsung untuk setiap rilis kompiler, sumber serangan harus berada di server build mereka di setidaknya satu rilis kompilator sebelumnya. Entah itu atau versi kompiler pertama yang mereka unduh sebagai biner harus dikompromikan.
sumber
Jika seseorang memiliki kode sumber untuk sistem kompiler / build yang outputnya seharusnya tidak bergantung pada apa pun selain konten dari file sumber yang disediakan, dan jika seseorang memiliki beberapa kompiler lain dan tahu bahwa mereka tidak semua berisi hack compiler yang sama, seseorang dapat pastikan seseorang mendapat eksekusi yang tergantung pada tidak lain dari kode sumber.
Misalkan seseorang memiliki kode sumber untuk paket compiler / linker (katakanlah Groucho Suite) ditulis sedemikian rupa sehingga hasilnya tidak akan bergantung pada perilaku yang tidak ditentukan, atau pada apa pun selain konten file sumber input, dan satu kompilasi / menghubungkan kode itu pada berbagai paket kompiler / penghubung yang diproduksi secara independen (katakanlah Harpo Suite, Chico suite, dan Zeppo Suite), menghasilkan serangkaian exeuctables yang berbeda untuk masing-masing (sebut mereka G-Harpo, G-Chico, dan G-Zeppo). Bukan hal yang tidak terduga untuk executable ini mengandung urutan instruksi yang berbeda, tetapi mereka harus identik secara fungsional. Membuktikan bahwa mereka identik secara fungsional dalam semua kasus, bagaimanapun, kemungkinan akan menjadi masalah yang sulit dipecahkan.
Untungnya, bukti seperti itu tidak diperlukan jika seseorang hanya menggunakan executable yang dihasilkan untuk satu tujuan: mengkompilasi suite Groucho lagi. Jika seseorang mengkompilasi suite Groucho menggunakan G-Harpo (menghasilkan GG-Harpo), G-Chico (GG-Chico), dan G-Zeppo (GG-Zeppo), maka ketiga file yang dihasilkan, GG-Harpo, GG-Chico , dan GG-Zeppo, seharusnya semua byte-untuk-byte identik. Jika file-file tersebut cocok, itu akan menyiratkan bahwa "virus kompiler" apa pun yang ada di dalamnya harus ada secara identik di semua file tersebut (karena ketiga file tersebut identik dengan byte-untuk-byte, tidak mungkin perilaku mereka berbeda di setiap cara).
Bergantung pada usia dan garis keturunan dari kompiler lain, dimungkinkan untuk memastikan bahwa virus semacam itu tidak mungkin ada di dalamnya. Sebagai contoh, jika seseorang menggunakan Macintosh antik untuk memberi makan kompiler yang ditulis dari awal pada 2007 melalui versi MPW yang ditulis pada 1980-an, kompiler 1980 tidak akan tahu di mana memasukkan virus dalam kompiler 2007. Dimungkinkan bagi seorang kompiler hari ini untuk melakukan analisis kode yang cukup mewah untuk mengetahuinya, tetapi tingkat perhitungan yang diperlukan untuk analisis tersebut akan jauh melebihi tingkat perhitungan yang diperlukan untuk hanya mengkompilasi kode, dan tidak bisa begitu saja tanpa diketahui di pasar di mana kecepatan kompilasi adalah nilai jual utama.
Saya berpendapat bahwa jika seseorang bekerja dengan alat kompilasi di mana byte dalam file yang dapat dieksekusi yang dihasilkan tidak boleh bergantung pada apa pun selain konten file sumber yang dikirimkan, dimungkinkan untuk mencapai kekebalan yang cukup baik dari Thompson. virus-gaya. Sayangnya, untuk beberapa alasan, non-determinisme dalam kompilasi tampaknya dianggap normal di beberapa lingkungan. Saya menyadari bahwa pada sistem multi-CPU, kompiler dapat berjalan lebih cepat jika dibolehkan memiliki aspek-aspek tertentu dari pembuatan kode berbeda-beda tergantung pada dua utas yang menyelesaikan pekerjaan terlebih dahulu.
Di sisi lain, saya tidak yakin saya melihat alasan bahwa penyusun / penghubung tidak boleh menyediakan mode "keluaran kanonik" di mana keluaran hanya bergantung pada file sumber dan "tanggal kompilasi" yang mungkin ditimpa oleh pengguna . Bahkan jika mengkompilasi kode dalam mode seperti itu memakan waktu dua kali lebih lama dari kompilasi normal, saya akan menyarankan bahwa akan ada nilai yang cukup besar untuk dapat membuat ulang "rilis build", byte untuk byte, seluruhnya dari bahan sumber, bahkan jika itu berarti bahwa rilis build akan memakan waktu lebih lama dari "build normal".
sumber