Jalankan program C tidak tepercaya di kotak pasir di Linux yang mencegahnya membuka file, forking, dll.?

110

Saya bertanya-tanya apakah ada cara untuk menjalankan program C yang tidak tepercaya di bawah kotak pasir di Linux. Sesuatu yang akan mencegah program membuka file, atau koneksi jaringan, atau forking, exec, dll?

Ini akan menjadi program kecil, tugas pekerjaan rumah, yang diunggah ke server dan tes unit dijalankan di atasnya. Jadi, program tersebut akan berumur pendek.

jujur
sumber
Apakah ini seperti program C tunggal yang Anda perlukan untuk dijalankan 1 kali selama 5 menit, atau sesuatu yang Anda perlukan untuk dijalankan terus-menerus?
bwawok
Ini akan menjadi program kecil yang diunggah dan pengujian unit dijalankan di atasnya. Jadi, program tersebut akan berumur pendek.
Frank
Distribusi apa yang digunakan sistem? Beberapa distribusi memiliki alat siap pakai untuk kotak pasir. Apakah sistem Anda memiliki model keamanan seperti SELinux atau AppArmor yang diaktifkan?
thkala
Saya menggunakan Fedora 13. Saya sedang mempelajari kebijakan SELinux Sandbox. Saya ingin tahu opsi lain apa yang ada.
Frank
6
Pertanyaan serupa tentang proses sandboxing / jailing di Linux atau Unix: * unix.stackexchange.com/q/6433/4319 * stackoverflow.com/q/3859710/94687 * stackoverflow.com/q/4410447/94687 * stackoverflow.com/q / 1019707/94687
imz - Ivan Zakharyaschev

Jawaban:

47

Saya telah menggunakan Systrace ke program sandbox yang tidak tepercaya baik secara interaktif maupun dalam mode otomatis. Ini memiliki ptrace()backend berbasis yang memungkinkan penggunaannya pada sistem Linux tanpa hak khusus, serta backend yang jauh lebih cepat dan lebih kuat yang membutuhkan patch kernel.

Dimungkinkan juga untuk membuat kotak pasir pada sistem mirip Unix menggunakan chroot(1), meskipun itu tidak semudah atau seaman. Linux Containers dan FreeBSD jail adalah alternatif yang lebih baik untuk chroot. Alternatif lain di Linux adalah menggunakan kerangka keamanan seperti SELinux atau AppArmor , yang akan saya usulkan untuk sistem produksi.

Kami akan dapat membantu Anda lebih banyak jika Anda diberi tahu seperti apa sebenarnya yang ingin Anda lakukan.

EDIT:

Systrace akan bekerja untuk kasus Anda, tetapi saya pikir sesuatu yang didasarkan pada Model Keamanan Linux seperti AppArmor atau SELinux lebih standar, dan dengan demikian lebih disukai, alternatif, tergantung pada distribusi Anda.

EDIT 2:

Meskipun chroot(1)tersedia di sebagian besar (semua?) Sistem mirip Unix, ia memiliki beberapa masalah:

  • Itu bisa dipatahkan. Jika Anda benar-benar akan mengkompilasi atau menjalankan program C yang tidak tepercaya di sistem Anda, Anda sangat rentan terhadap masalah ini. Dan jika murid-murid Anda seperti saya, seseorang AKAN mencoba untuk keluar dari penjara.

  • Anda harus membuat hierarki sistem file independen penuh dengan semua yang diperlukan untuk tugas Anda. Anda tidak perlu memiliki kompiler di chroot, tetapi apapun yang diperlukan untuk menjalankan program yang dikompilasi harus disertakan. Meskipun ada utilitas yang membantu hal ini, itu tetap tidak sepele.

  • Anda harus mempertahankan chroot. Karena independen, file chroot tidak akan diperbarui bersama dengan distribusi Anda. Anda harus membuat ulang chroot secara teratur, atau menyertakan alat pembaruan yang diperlukan di dalamnya, yang pada dasarnya memerlukan distribusi Linux yang lengkap. Anda juga harus menyimpan data sistem dan pengguna (kata sandi, file input, dll) yang disinkronkan dengan sistem host.

  • chroot()hanya melindungi sistem file. Itu tidak mencegah program jahat dari membuka soket jaringan atau yang ditulis dengan buruk dari menyedot setiap sumber daya yang tersedia.

Masalah penggunaan sumber daya adalah umum di antara semua alternatif. Kuota sistem file akan mencegah program mengisi disk. Pengaturan yang tepat ulimit( setrlimit()di C) dapat melindungi dari penggunaan memori yang berlebihan dan serangan fork, serta menghentikan CPU hogs. nice(1)dapat menurunkan prioritas program tersebut sehingga komputer dapat digunakan untuk tugas-tugas yang dianggap lebih penting tanpa masalah.

thkala
sumber
systrace bekerja untuk saya untuk program sederhana, tetapi macet tanpa batas saat GNU sebagai (1) dijalankan oleh GCC. Jadi saya menyerah. Ini adalah bug yang tidak diperbaiki di systrace: forum.soft32.com/linux/…
poin
Adakah cara untuk memastikan bahwa memori bersama, antrian pesan, dan semaphore tidak dibagi antara proses kotak pasir?
daveagp
1
Tautan systrace rusak.
Collin
2
Bagaimana dengan Firejail? Anda tidak perlu mempertahankan fs lagi menggunakannya.
m3nda
18

Saya menulis gambaran umum tentang teknik sandboxing di Linux baru-baru ini. Saya pikir pendekatan termudah Anda adalah menggunakan wadah Linux (lxc) jika Anda tidak keberatan tentang forking dan sebagainya, yang tidak terlalu penting di lingkungan ini. Anda dapat memberikan proses tersebut sistem file root hanya baca, koneksi jaringan loopback terisolasi, dan Anda masih dapat membunuhnya dengan mudah dan mengatur batas memori, dll.

Seccomp akan menjadi agak sulit, karena kode tersebut bahkan tidak dapat mengalokasikan memori.

Selinux adalah opsi lain, tetapi saya pikir ini mungkin lebih berhasil daripada wadah.

Justin Cormack
sumber
6

Anda dapat menggunakan Qemu untuk menguji tugas dengan cepat. Prosedur di bawah ini membutuhkan waktu kurang dari 5 detik pada laptop saya yang berusia 5 tahun.

Mari kita asumsikan siswa harus mengembangkan program yang mengambil int unsigned, masing-masing pada barisnya sendiri, sampai baris dengan "-1" tiba. Program kemudian harus menghitung rata-rata semua int dan output "Rata-rata:% f". Inilah cara Anda dapat menguji program yang sepenuhnya terisolasi:

  1. Pertama, dapatkan root.bindari Jslinux, kita akan menggunakannya sebagai userland (memiliki compiler-C tcc):

    wget https://github.com/levskaya/jslinux-deobfuscated/raw/master/root.bin

  2. Kami ingin memasukkan kiriman siswa root.bin, jadi siapkan perangkat loop:

    sudo losetup /dev/loop0 root.bin

    (Anda juga dapat menggunakan fuseext2 untuk ini, tetapi tidak terlalu stabil. Jika stabil, Anda tidak memerlukan root untuk semua ini)

  3. Buat direktori kosong:

    mkdir mountpoint

  4. Mount root.bin:

    sudo mount /dev/loop0 mountpoint

  5. Masuk ke sistem file yang terpasang:

    cd mountpoint.

  6. Memperbaiki hak:

    sudo chown -R `whoami` .

  7. mkdir -p etc/init.d
  8. vi etc/init.d:

    #!/bin/sh
    cd /root
    echo READY 2>&1 > /dev/ttyS0
    tcc assignment.c 2>&1 > /dev/ttyS0
    ./a.out 2>&1 > /dev/ttyS0
    
  9. chmod +x etc/init.d/rcS

  10. Salin kiriman ke VM:

    cp ~/student_assignment.c root/assignment.c

  11. Keluar dari VM root FS:

    cd ..

  12. sudo umount mountpoint
  13. Sekarang gambar sudah siap, kita hanya perlu menjalankannya. Ini akan mengkompilasi dan menjalankan pengiriman setelah booting.
  14. mkfifo /tmp/guest_output
  15. Buka terminal terpisah dan mulai dengarkan keluaran tamu:

    dd if=/tmp/guest_output bs=1

  16. Di terminal lain:

    qemu-system-i386 -kernel vmlinuz-3.5.0-27-generic -initrd root.bin -monitor stdio -nographic -serial pipe:/tmp/guestoutput (Saya baru saja menggunakan kernel Ubuntu di sini, tetapi banyak kernel akan berfungsi)

  17. Jika guest output menampilkan "READY", Anda dapat mengirim kunci ke VM dari prompt qemu. Misalnya, untuk menguji tugas ini, Anda bisa melakukannya

    (qemu) sendkey 1
    (qemu) sendkey 4
    (qemu) sendkey ret
    (qemu) sendkey 1
    (qemu) sendkey 0
    (qemu) sendkey ret
    (qemu) sendkey minus
    (qemu) sendkey 1
    (qemu) sendkey ret
    
  18. Sekarang Average = 12.000000akan muncul di pipa keluaran tamu. Jika tidak, siswa tersebut gagal.

  19. Keluar dari qemu: quit

Program yang lulus tes ada di sini: https://stackoverflow.com/a/14424295/309483 . Gunakan saja, tcclib.hbukan stdio.h.

Janus Troelsen
sumber
5

Coba Linux mode Pengguna . Ini memiliki sekitar 1% overhead kinerja untuk pekerjaan intensif CPU, tetapi mungkin 6 kali lebih lambat untuk pekerjaan intensif I / O.

poin
sumber
4

Firejail adalah salah satu alat paling komprehensif untuk melakukannya - ini mendukung seccomp, wadah sistem file, kemampuan, dan lainnya:

https://firejail.wordpress.com/features-3/

Federico
sumber
Jawaban ini luar biasa, sangat layak mendapat lebih banyak suara positif mengingat firejail secara aktif dikelola dengan dokumentasi yang bagus, mencakup sebagian besar jika tidak semua jawaban lain dan dirancang agar relatif mudah digunakan.
Jeff Hykin
3

Menjalankannya di dalam mesin virtual harus menawarkan semua keamanan dan batasan yang Anda inginkan.

QEMU akan cocok untuk itu dan semua pekerjaan (mengunduh aplikasi, memperbarui gambar disk, memulai QEMU, menjalankan aplikasi di dalamnya, dan menyimpan keluaran untuk pengambilan nanti) dapat dibuat skrip untuk pengujian otomatis.

Laurent Parenteau
sumber
2
Saya tidak tahu tentang OP, tetapi meluncurkan VM per program pengujian tidak akan dapat diterima dalam banyak kasus. Di lingkungan saya (saya seorang TA), ada sebanyak 200 siswa yang mengirimkan 10-12 program masing-masing dalam waktu 2 jam. Tidak ada program yang berjalan selama lebih dari 10 detik waktu CPU, tetapi ketika kiriman menumpuk, kami mendapatkan waktu perputaran 15 menit atau lebih. Memperkenalkan VM untuk setiap program akan mendorong waktu CPU ke 60 detik atau lebih per program dan saya sama sekali tidak ingin memikirkan tentang waktu perputaran. Mungkin VM per sesi, tapi tidak mungkin kami bisa melakukan itu per program ...
Thkala
@ Thkala Ini adalah poin yang bagus. Saya suka ide QEMU tetapi memulai VM untuk setiap pengiriman itu tidak baik.
Frank
Nah, dalam hal ini, biarkan VM yang sama tetap berjalan sepanjang waktu.
Laurent Parenteau
Bisakah Anda melakukan sesuatu menggunakan snapshot dari vm yang sudah di-boot dan siap untuk mengkompilasi & menjalankan kode? FYI, vm tidak selalu kebal terhadap tindik. Anda juga dapat membangun versi perangkat keras ini - sistem kecil yang mem-boot gambar resume dari media hanya-baca atau melalui jaringan dan memberikan keluaran melalui jaringan atau serial, kemudian di-boot ulang untuk selanjutnya. Ada beberapa kemajuan boot cepat yang membuat linux aktif dalam beberapa detik.
Chris Stratton
@thkala: Itu berarti Anda membutuhkan kurang dari 3 detik per pengiriman jika Anda menjalankannya secara serial. Pendekatan yang saya posting mungkin membutuhkan waktu sekitar 3 detik pada mesin modern (secara serial). Jika Anda memparalelkan (yang mungkin juga Anda lakukan), itu akan cukup cepat.
Janus Troelsen
3

Ketika membahas sanboxing berdasarkan ptrace (strace), periksa:

" sydbox " sandbox dan " pinktrace " pustaka pemrograman (ini C99 tetapi ada binding ke python dan ruby ​​sejauh yang saya tahu).

Tautan yang terkumpul terkait dengan topik:

http://www.diigo.com/user/wierzowiecki/sydbox

(maaf itu bukan tautan langsung, tetapi belum cukup poin reputasi)

Grzegorz Wierzowiecki
sumber
1

Perpustakaan ini harus memenuhi tujuan Anda dengan baik

http://sandbox.sourceforge.net

Semoga berhasil!

thoaionline.dll
sumber
8
Ini sepertinya tidak dipertahankan secara aktif. Itu juga tampaknya membutuhkan tambalan kernel Linux, yang akan membuatnya sebagian besar tidak berguna mengingat versi terbarunya tanggal kembali ke 2003.
thkala
1

Ini juga tampaknya menjanjikan. Kotak pasir sistem file untuk Linux menggunakan penyadapan syscall.

https://github.com/adtac/fssb

mauron85
sumber
-1

ok terima kasih untuk semua jawaban mereka banyak membantu saya. Tetapi saya akan menyarankan tidak satupun dari mereka sebagai solusi untuk orang yang mengajukan pertanyaan asli. Semua alat yang disebutkan membutuhkan banyak pekerjaan untuk tujuan menguji kode siswa sebagai guru, tutor, prof. Cara terbaik dalam hal ini menurut saya virtualbox. Ok, ini mengemulasi sistem x68 lengkap dan tidak ada hubungannya dengan arti sandboxing dengan cara ini tetapi jika saya membayangkan guru pemrograman saya, itu akan menjadi yang terbaik untuknya. Jadi "apt-get install virtualbox" pada sistem berbasis debian, semua yang lain menuju ke http://virtualbox.org/ , buat vm, tambahkan iso, klik install, tunggu beberapa saat dan beruntung. Akan jauh lebih mudah digunakan untuk mengatur mode-pengguna-linux atau melakukan beberapa hal yang berat ...

Dan jika Anda memiliki ketakutan tentang siswa Anda meretas Anda, saya kira Anda memiliki masalah otoritas dan solusi untuk itu akan mengancam mereka bahwa Anda akan menuntut siang hari yang hidup dari mereka jika Anda dapat membuktikan hanya satu gigitan perangkat lunak perusak dalam pekerjaan yang mereka berikan kamu...

Juga jika ada kelas dan 1% darinya adalah sebaik dia bisa melakukan hal-hal seperti itu, jangan membuat mereka bosan dengan tugas-tugas sederhana seperti itu dan beri mereka beberapa tugas besar di mana mereka harus membuat kode lagi. Pembelajaran integratif adalah yang terbaik untuk semua orang, jadi jangan teruskan pada struktur lama yang menemui jalan buntu ...

Dan penyebabnya, jangan pernah menggunakan komputer yang sama untuk hal-hal penting (seperti menulis pengesahan dan ujian), yang Anda gunakan untuk hal-hal seperti menjelajahi web dan menguji perangkat lunak.

Gunakan komputer offline untuk hal-hal penting dan komputer online untuk semua hal lainnya.

Namun untuk semua orang yang bukan guru paranoid (tidak ingin menyinggung siapa pun, saya hanya berpendapat bahwa Anda harus mempelajari dasar-dasar tentang keamanan dan masyarakat kita sebelum Anda mulai menjadi guru programer ...)

... di mana saya ... untuk orang lain:

selamat meretas !!

rohySeentrusted
sumber