Cara mengkompilasi kompiler C dari awal, lalu kompilasi Unix / Linux dari awal

64

Katakanlah saya bekerja untuk organisasi layanan besar di luar AS / Inggris. Kami menggunakan server UNIX dan Linux secara luas.

Membaca artikel ini menyebutkan bahwa akan mudah untuk memasukkan pintu belakang ke kompiler C, maka setiap kode yang dikompilasi dengan kompiler itu juga akan berisi pintu belakang. Sekarang diberi kebocoran baru-baru ini mengenai mandat NSA / GCHQ untuk menempatkan backdoors / kelemahan dalam semua metode enkripsi, perangkat keras dan perangkat lunak, kompiler sekarang merupakan titik kritis kegagalan. Berpotensi semua distribusi standar UNIX / Linix dapat dikompromikan. Kami tidak dapat membiarkan sistem, data, dan data pelanggan kami dikompromikan oleh pemerintah jahat.

Dengan informasi ini, saya ingin membangun kompiler tepercaya dari awal, kemudian saya memiliki basis aman untuk dibangun sehingga saya dapat membangun Sistem Operasi dan aplikasi dari kode sumber menggunakan kompiler itu.

Pertanyaan

Apa yang benar (dan cara aman) untuk mengkompilasi kompiler dari kode sumber (skenario yang tampaknya seperti ayam-telur) kemudian mengkompilasi distribusi Unix / Linux tepercaya dari awal?

Anda dapat menganggap saya atau orang lain memiliki kemampuan untuk membaca dan memahami kode sumber untuk kelemahan keamanan, sehingga kode sumber akan diperiksa terlebih dahulu sebelum dikompilasi. Yang benar-benar saya cari adalah panduan kerja untuk menghasilkan kompiler ini dari awal dengan aman dan dapat digunakan untuk mengkompilasi kernel, bagian lain dari OS dan aplikasi.

Tumpukan keamanan harus dimulai pada tingkat dasar jika kita ingin memiliki kepercayaan pada sistem operasi atau aplikasi yang berjalan pada tumpukan itu. Ya saya mengerti mungkin ada hardware backdoor yang dapat memasukkan beberapa kode mikro ke dalam kompiler saat ini sedang dibangun. Tidak banyak yang bisa kita lakukan tentang itu untuk saat ini kecuali mungkin menggunakan chip yang tidak dirancang di AS. Mari kita selesaikan layer ini sebagai permulaan dan anggap saya dapat membangunnya di komputer lama sebelum berpotensi adanya backdoors.

Seperti yang dikatakan Bruce Schneier: "Kepada para insinyur, saya mengatakan ini: kami membangun internet, dan beberapa dari kami telah membantu menumbangkannya. Sekarang, kami yang mencintai kebebasan harus memperbaikinya."

Tautan ekstra:

David J
sumber
7
Sial, ini pertanyaan yang sangat menarik dan saya tidak ingin memigrasikannya tetapi saya tidak benar-benar berpikir tentang topik di sini. Itu lebih cocok untuk stackoverflow.com karena pertanyaan dasar Anda adalah tentang bagaimana mengkompilasi kompiler dari awal yang cukup banyak OS agnostik dan sangat banyak pertanyaan pemrograman. Jika Anda tidak mendapatkan jawaban di sini setelah beberapa saat, pertimbangkan untuk menggunakan tautan "panji" di bawah tag pertanyaan Anda dan minta moderator untuk memindahkan ini ke SO.
terdon
2
@terdon Ini mungkin sebenarnya lebih cocok untuk Programmers.SE karena ini lebih tentang masalah pemrograman umum daripada masalah pengembangan spesifik. Bahkan, mungkin ada duplikat di sana .
CVn
2
GCC adalah open source, bagaimana cara backdoor dimasukkan?
Michael Pankov
2
Ingatlah bahwa exploit Thompson yang stabil membutuhkan kode yang dapat dikenali ketika program login atau kompiler sedang dikompilasi. Jika Anda bisa secara manual mengubah sumber menjadi bentuk yang tidak dikenali oleh kompiler sebagai salah satu program tersebut, pintu belakang tidak akan disebarkan.
Russell Borogove
2
@Constantius - baca artikel Thompson yang ditautkan di baris pertama. Siapa yang mengkompilasi kompiler?
Russell Borogove

Jawaban:

30

AFAIK satu-satunya cara untuk sepenuhnya yakin akan keamanan adalah dengan menulis kompiler dalam bahasa assembly (atau memodifikasi disk secara langsung sendiri ). Hanya dengan begitu Anda dapat memastikan bahwa kompiler Anda tidak memasukkan backdoor - ini berfungsi karena Anda benar-benar menghilangkan kompiler sepenuhnya.

Dari sana, Anda dapat menggunakan kompiler dari-awal Anda untuk mem-bootstrap mis. GNU toolchain. Kemudian Anda dapat menggunakan rantai alat kustom untuk mengkompilasi sistem Linux Dari Awal .

Perhatikan bahwa untuk mempermudah Anda, Anda bisa memiliki kompiler perantara kedua, ditulis dalam C (atau bahasa apa pun lainnya). Jadi Anda akan menulis compiler A di assembly, kemudian menulis ulang compiler itu di C / C ++ / Python / Brainfuck / apa pun untuk mendapatkan compiler B, yang akan Anda kompilasi menggunakan kompiler A. Kemudian Anda akan menggunakan kompiler B untuk mengkompilasi gcc dan teman-teman.

strugee
sumber
13
Meski begitu, ini masih hanya melindungi terhadap kompiler jahat. Anda masih perlu mempercayai sistem yang dijalankan oleh kompiler. Tidak ada perangkat lunak yang terisolasi.
CVn
3
Apa pun yang otonom secara inheren berbahaya. Anda secara efektif mengusulkan kompilator toolchain (meskipun aneh) yang artinya mungkin dapat dimodifikasi persis seperti yang Anda coba hindari. Bahkan lebih baik, itu dapat dimodifikasi dalam perjalanan melalui MitM.
strugee
1
Kalian harus menyadari bahwa jawaban ini berasal dari seorang anak berusia 15 tahun. Terus tegar!
mtahmed
3
Orang tidak boleh lupa untuk juga menulis editor kode dari awal - siapa yang tahu apakah <code> vim </code> yang dikompilasi sebelumnya atau <code> vim </code> yang Anda kompilasi dengan kompiler yang baik dari sumber yang telah diaudit hanya menggunakan yang terinfeksi <code> vim </code> dapat dipercaya?
Hagen von Eitzen
1
Jangan pernah lupa, bahwa kecuali Anda secara pribadi menulis kode mesin pertama (bukan kode mesin perakitan aktual), dan Anda adalah ahli dalam mengenali celah keamanan yang curang, dan membaca dan memeriksa setiap baris kode yang Anda kompilasi ... atau setidaknya tahu orang yang melakukan itu secara pribadi , dan percaya padanya untuk melakukan ini .... semua ini tidak akan membantu sama sekali. Itu sebabnya mencoba Kickstarter ini, menghancurkan seluruh intinya. Yaitu: kepercayaan tinggi.
Evi1M4chine
22

Satu cara yang mungkin, meskipun akan memakan waktu yang sangat lama dalam praktik, adalah kembali ke akarnya. Pengembangan GNU dimulai pada tahun 1984, dan versi asli Minix (yang digunakan selama pengembangan Linux awal untuk keperluan bootstrap) dirilis pada tahun 1987.

Seluruh jawaban ini didasarkan pada premis Anda bahwa "[Anda] atau orang lain memiliki kemampuan untuk membaca dan memahami kode sumber untuk kelemahan keamanan, sehingga kode sumber akan diperiksa terlebih dahulu sebelum kompilasi", dan bahwa Anda dapat mempercayai hasil analisis seperti itu. . Tanpa itu, jawaban ini mungkin lebih buruk daripada tidak berharga, karena Anda akan menghabiskan banyak waktu tanpa manfaat sama sekali.

Jika Anda dapat menemukan salinan buku Minix asli dengan kode sumber, Anda dapat mengetiknya dari buku itu. Kompilasi, dan kemudian gunakan dekompiler yang berbeda pada sistem yang berbeda untuk memverifikasi bahwa kompiler menghasilkan output biner bahasa mesin yang diharapkan. (Kode ini hanya 12.000 baris, mungkin C, sehingga hal itu memakan waktu tetapi masih masuk akal jika Anda serius tentang proyek semacam itu.) Anda bahkan dapat menulis disassembler Anda sendiri; seharusnya tidak terlalu sulit.

Raih versi tertua dari utilitas GNU yang bisa Anda dapatkan (karena mungkin kode-kode itu lebih sedikit dan lebih sedikit ketergantungan pada perpustakaan eksternal), baca kode, bangun untuk Minix (ini mungkin memerlukan beberapa pekerjaan, meskipun; apa yang Anda lakukan Yang benar-benar ingin dihindari adalah membuat penyesuaian pada kode sumber, karena itu akan membuat penambahan tambalan nantinya sangat rawan kesalahan) dan melalui siklus pembongkaran-verifikasi yang serupa untuk alat-alat GNU. Pada saat itu Anda mempercayai OS dan toolchain, jadi Anda hanya perlu melalui kode sumber di patchset (apa pun yang tidak di patchset sudah dipercaya), tetapi alat tersebut akan tetap sangat primitif dan kasar dibandingkan dengan apa yang Anda gunakan untuk hari ini. Sebagai contoh, jangan mengharapkan sesuatu yang lebih dari fungsionalitas paling dasar dari alat sistem.Baca banyak XKCD.

Pada titik tertentu, Anda akan memiliki sistem yang dapat mengkompilasi dan mem-bootstrap kernel Linux versi awal, seperti yang dilakukan pada awal 1990-an ketika Linux mulai mendapatkan daya tarik di antara para peretas. Saya menyarankan migrasi ke Linux pada saat itu (membangun kembali pustaka sistem dan toolchain terhadap Linux, membangun kernel Linux, boot ke Linux dan mungkin membangun kembali kernel Linux dan GNU toolchain dalam Linux; yang terakhir membuktikan bahwa sistem sekarang mandiri hosting), tetapi sebagian besar terserah Anda. Terus memverifikasi tambalan, menambal kernel, pustaka dan alat GNU dasar, dan membangun kembali sampai Anda mendapatkan versi modern.

Saat itulah Anda memiliki OS dan kompiler dasar tepercaya yang dapat digunakan untuk membangun perangkat lunak modern. Pada saat itu, Anda dapat mengikuti misalnya panduan Linux From Scratch untuk membangun sistem yang mampu melakukan tugas-tugas yang bermanfaat .

Pada titik mana pun sistem "kompiler" tidak dapat dihubungkan ke jaringan dengan cara apa pun (termasuk sebagai VM pada host jaringan); Anda akan berisiko penetrasi melalui komponen berkemampuan jaringan apa pun termasuk kernel. Jika Anda khawatir tentang serangan kompiler Thompson , Anda harus berharap bahwa setiap host VM juga dapat dikompromikan. Gunakan sneakernet untuk mendapatkan kode sumber dan binari dari host fisik tempat Anda mengompil. Harapkan kesulitan mendapatkan dan mematikan file sistem setidaknya sebelum Anda sampai ke titik di mana dukungan penyimpanan massal USB diimplementasikan. Jika Anda benar-benar paranoid, cetak daftar kode sumber dan ketik dengan tangan (dan berharap driver printer dan printer tidak memiliki kode yang sama di dalamnya), atau baca kode pada satu monitor komputer dan ketikkan ke komputer lain secara fisik di sebelah tetapi tidak terhubung.

Ya, ini akan memakan banyak waktu. Tetapi keuntungan dari pendekatan ini adalah bahwa setiap langkah bersifat inkremental, yang berarti bahwa akan lebih sulit bagi apa pun yang berbahaya untuk lolos kecuali itu secara bertahap diperkenalkan selama periode banyak versi; ini karena set perubahan pada setiap langkah relatif kecil dan karenanya lebih mudah untuk dilihat. Bandingkan tambalan dengan changelog dan pastikan Anda dapat menentukan entri changelog mana yang sesuai dengan setiap perubahan dalam kode sumber. Sekali lagi, ini memang mengasumsikan bahwa Anda memiliki kemampuan (mungkin melalui seseorang yang Anda percayai) untuk memverifikasi bahwa perubahan tersebut belum dimasukkan ke dalam basis kode, tetapi harus membuat Anda sedekat mungkin dengan sistem tepercaya sebagai perangkat lunak saja kecuali- Pendekatan firmware bisa.

sebuah CVn
sumber
Metode pembongkaran-verifikasi sangat cacat, karena masih membuat asumsi besar, bahwa mesin verifikasi sepenuhnya dapat dipercaya. Kecuali Anda membuat mesin itu dan perangkat lunaknya dari nol, atau mengenal orang yang melakukannya secara pribadi dan percaya padanya, ini tidak akan terjadi. Jadi ini masih tidak aman. Maaf. …… Juga, dalam hal-hal ini “sedekatnya dengan ...” masih berarti “tidak aman”, karena hanya membutuhkan satu tempat yang tidak dapat dipercaya untuk menghancurkan seluruh titik.
Evi1M4chine
9

Jika Anda membutuhkan kompiler tepercaya, Anda bisa melihat karya akademis, seperti proyek compcert . Ini adalah kompiler yang dibangun oleh INRIA (laboratorium publik IT Prancis) yang dirancang untuk '' disertifikasi '', yaitu untuk menghasilkan executable yang secara semantik setara dengan kode (dan tentu saja, telah dibuktikan secara matematis).

lororget
sumber
1
Setiap orang membutuhkan kompiler tepercaya. Bagaimana cara kerja matematika bahwa mereka dapat menghasilkan kompiler "tepercaya"?
David J
@ David J Bootstrapping, kemungkinan besar. Buat beberapa bagian kecil yang benar-benar dapat Anda verifikasi dan buktikan dengan benar, kemudian gunakan sebagai dasar untuk membangun kompiler yang lebih kompleks.
CVn
1
"" "Apa yang membedakan CompCert C dari kompiler produksi lainnya, adalah CompCert diverifikasi secara formal, menggunakan bukti matematis berbantuan mesin, untuk dibebaskan dari masalah miskompilasi." "" Compcert.inria.fr/compcert-C.html Kompilasi tidak empiris seperti dulu.
lgeorget
1
@ MichaelKjörling yang mungkin tidak mempertimbangkan bahwa kernel dapat dikompromikan untuk memasukkan pintu belakang ke sumber kompiler ketika dibaca oleh kompiler
ratchet freak
1
Saya juga menemukan tautan ini yang bisa berfungsi juga.
David J
2

Walaupun secara manual membuat kompiler Anda sendiri sebagai titik awal adalah yang paling aman, opsi lain adalah menginstal sistem dari CD instalasi berumur 5 (atau 10) tahun yang Anda percayai dibuat sebelum eksploit ini ada. Kemudian gunakan itu sebagai dasar untuk mengumpulkan sumber baru yang diaudit.

sambler
sumber
5
Serangan itu sudah diketahui publik sejak 1984. Agaknya Thompson bukan yang pertama memikirkan kemungkinan itu. Kembali sejauh itu berarti bahwa sebagian besar hal yang kita terima hari ini tidak ada; pertimbangkan apa yang mampu dilakukan komputer 20 tahun lalu dan bandingkan dengan keadaan mereka saat ini. Bahkan sistem bootstrap Linux asli Minix tidak dirilis sampai '87 , dan pengembangan GNU dimulai pada '84. Jadi sementara dalam teori ini mungkin menjawab pertanyaan, dalam praktiknya sebagian besar tidak berguna sebagai jawaban.
CVn
2
Komputer paling awal yang berpotensi bisa saya dapatkan adalah komputer 286. Saya harus melihat apakah kakek nenek saya masih memilikinya.
David J
1
Poin bonus untuk benar-benar mempertimbangkan itu :-). @ DavidvidJ
11684
@ MichaelKjörling: Tidak juga; karena itu hanya membuat rantai bootstrap Anda lebih lama. Tapi mungkin tidak selama menulis kompiler Anda sendiri dari awal dalam bahasa mesin.
Evi1M4chine