Praktik terbaik untuk pelaksanaan kode yang tidak dipercaya

31

Saya punya proyek di mana saya harus mengizinkan pengguna untuk menjalankan kode python yang sewenang-wenang dan tidak dipercaya ( sedikit seperti ini ) terhadap server saya. Saya cukup baru untuk python dan saya ingin menghindari membuat kesalahan yang memperkenalkan lubang keamanan atau kerentanan lainnya ke dalam sistem. Apakah ada praktik terbaik yang tersedia, bacaan yang disarankan, atau petunjuk lain yang dapat Anda berikan agar layanan saya dapat digunakan tetapi tidak dapat disalahgunakan?

Inilah yang saya pertimbangkan sejauh ini:

  • Hapus __builtins__dari execkonteks untuk melarang penggunaan paket yang berpotensi berbahaya seperti os. Pengguna hanya akan dapat menggunakan paket yang saya berikan kepada mereka.
  • Gunakan utas untuk menerapkan batas waktu yang wajar.
  • Saya ingin membatasi jumlah total memori yang dapat dialokasikan dalam execkonteks, tapi saya tidak yakin apakah itu mungkin.

Ada beberapa alternatif untuk straight exec, tapi saya tidak yakin yang mana dari ini akan membantu di sini:

  • Menggunakan a ast.NodeVisitoruntuk menangkap setiap upaya untuk mengakses objek yang tidak aman. Tapi benda apa yang harus saya larang?
  • Mencari sembarang garis bawah pada input. (kurang anggun dari opsi di atas).
  • Menggunakan PyPyatau sesuatu yang mirip dengan sandbox kode.

CATATAN: Saya sadar bahwa setidaknya ada satu juru bahasa berbasis JavaScript. Itu tidak akan berfungsi dalam skenario saya.

pswg
sumber
3
@ MartijnPieters: Luar Biasa. Mungkin layak mendapat jawaban, jika Anda merangkum masing-masing.
Robert Harvey
Pertimbangkan juga: sampah yang tertinggal di disk, jaringan (jangan biarkan mereka mengirim spam atau apa pun), izin ke file lain (membaca file Anda). Bahkan mengeluarkan sementara loop dapat menghancurkan mekanisme CD ... Saya akan pergi untuk virtualisasi (penjara atau beberapa kvm beri nama) atau setidaknya pengguna dengan hampir tidak ada hak istimewa. Tetapkan jumlah memori dan memori yang wajar untuk keuntungan program Anda sendiri.
kyticka
1
Coba PyPy :> Sandboxing: PyPy memberikan kemampuan untuk menjalankan kode yang tidak terpercaya dengan cara yang sepenuhnya aman.
Vorac

Jawaban:

28

Kotak pasir Python sulit . Python secara inheren tidak dapat ditinjau, pada berbagai tingkatan.

Ini juga berarti Anda dapat menemukan metode pabrik untuk tipe tertentu dari tipe itu sendiri, dan membuat yang baru objek tingkat rendah , yang akan dijalankan langsung oleh penerjemah tanpa batasan.

Berikut adalah beberapa contoh menemukan cara kreatif untuk keluar dari kotak pasir Python:

Ide dasarnya adalah selalu menemukan cara untuk membuat tipe dasar Python; fungsi dan kelas dan keluar dari shell dengan mendapatkan penerjemah Python untuk mengeksekusi bytecode sewenang-wenang (tidak dicentang!).

Hal yang sama dan lebih berlaku untuk execpernyataan ( exec()berfungsi dalam Python 3).

Jadi, Anda ingin:

  • Kontrol ketat kompilasi byte kode Python, atau setidaknya pasca-proses bytecode untuk menghapus akses ke nama yang dimulai dengan garis bawah.

    Ini membutuhkan pengetahuan mendalam tentang bagaimana interpreter Python bekerja dan bagaimana bytecode Python terstruktur. Objek kode bersarang; bytecode modul hanya mencakup tingkat atas pernyataan, masing-masing fungsi dan kelas terdiri dari urutan bytecode mereka sendiri ditambah metadata, berisi objek bytecode lain untuk fungsi dan kelas bersarang, misalnya.

  • Anda perlu daftar putih modul yang dapat digunakan. Dengan hati-hati.

    Modul python berisi referensi ke modul lain . Jika Anda mengimpor os, ada nama lokal osdi namespace modul Anda yang merujuk ke osmodul. Ini dapat mengarahkan penyerang yang gigih ke modul yang dapat membantu mereka keluar dari kotak pasir. The picklemodul, misalnya, memungkinkan Anda memuat kode objek sewenang-wenang misalnya, jadi jika setiap jalan melalui modul daftar putih mengarah ke picklemodul, Anda memiliki masalah masih.

  • Anda harus benar-benar membatasi kuota waktu. Bahkan kode yang paling netral pun masih dapat mencoba dijalankan selamanya, dengan mengikat sumber daya Anda.

Lihatlah RestrictedPython , yang mencoba memberi Anda kontrol bytecode yang ketat. RestrictedPythonmengubah kode Python menjadi sesuatu yang memungkinkan Anda mengontrol nama, modul, dan objek apa yang diizinkan dalam Python 2.3 hingga 2.7.

Jika RestrictedPythoncukup aman untuk tujuan Anda tergantung pada kebijakan yang Anda terapkan. Tidak mengizinkan akses ke nama-nama yang dimulai dengan garis bawah dan membuat daftar putih modul-modul akan menjadi permulaan.

Menurut pendapat saya, satu-satunya pilihan yang benar-benar kuat adalah menggunakan Mesin Virtual yang terpisah, yang tanpa akses jaringan ke dunia luar yang Anda hancurkan setelah setiap kali dijalankan. Setiap skrip baru diberi VM baru. Dengan cara itu bahkan jika kode berhasil keluar dari kotak pasir Python Anda (yang bukan tidak mungkin) semua penyerang mendapatkan akses untuk berumur pendek dan tanpa nilai.

Martijn Pieters
sumber
10

TL; DR Gunakan chroot / jail dan jalankan sebagai pengguna khusus tanpa hak istimewa.

Praktik terbaik untuk mengeksekusi kode yang tidak dipercaya adalah memisahkannya melalui kotak pasir sistem . Untuk keamanan paling:

  • buat wadah dengan hanya Python dan dependensinya serta dependensi penampung
  • buat wadah tanpa semua perangkat yang tidak mutlak diperlukan (mis. jaringan dan penyimpanan)
  • buat wadah dengan batasan pada memori dan proses penggunaan
  • buat ulang wadah dengan setiap proses (atau setidaknya dengan setiap pengguna unik dan periode waktu maks)
  • berjalan sebagai pengguna dengan hak istimewa yang paling tidak dibutuhkan
  • dijalankan sebagai pengguna yang tidak memiliki izin untuk menulis file

Anda juga mengikuti praktik standar untuk menjalankan berbagai hal dengan aman di chroot. Anda dapat membangun kembali sistem file chroot dengan setiap panggilan juga sangat paranoid. Biasanya Anda hanya membuat pengguna tidak dapat membuat modifikasi pada sistem file tempat chroot berjalan.

dietbuddha
sumber
Ini adalah satu-satunya hal di mana Anda akan jauh bahkan yakin Anda sudah benar - berikan itu proses sendiri.
Michael Kohne
3

Tidak mungkin Anda bisa melakukan ini dengan aman.

Jika Anda ingin melakukan sesuatu seperti ini dengan aman, Anda harus mulai dengan memiliki implementasi python Anda sendiri yang berjalan di lingkungan yang sepenuhnya terkontrol, lebih disukai berjalan di browser pengguna daripada di sistem Anda. Anda mungkin mulai dengan Jython (python untuk java) dan mengemasnya sebagai java applet. Karena itu akan berjalan di kotak pasir java, pada mesin pengguna, sistem Anda akan cukup aman.

ddyer
sumber
4
Pertanyaan tentang keamanan adalah untuk servernya, bukan untuk mesin klien. Bahaya keamanan potensial Java, seperti yang terjadi pada teknologi web lainnya, adalah bahwa server dapat digunakan untuk menggunakan program yang berbahaya bagi klien.
ddyer
1
@grasGendarme sangat mirip dengan cerita baru tentang kecelakaan pesawat yang benar-benar memberi tahu Anda betapa jarangnya itu; cerita tentang lubang keamanan java memberi tahu Anda bahwa java relatif aman. Anda tidak akan pernah mendapatkan cerita seperti itu tentang C karena respons yang akan Anda dapatkan adalah "yah; jika Anda menjalankannya, itu akan melakukan apa pun yang diinginkannya"
Richard Tingle
2

Seperti yang dikatakan Martijn di atas, ini benar-benar sulit dengan Python. Terus terang karena Python sangat introspeksi, saya tidak berpikir itu mungkin dengan membatasi fitur bahasa. Dan jika Anda mendapatkan kotak pasir yang berfungsi untuk satu versi Python, ada kemungkinan versi berikutnya akan merusaknya.

Saya akan melihat PyPy alih-alih CPython standar. Singkatnya, ini adalah implementasi alternatif yang sesuai dari Python. Ini memiliki beberapa keunggulan dan fitur yang berbeda, dan salah satunya adalah sandboxing melalui mengganti panggilan sistem alih-alih membatasi fitur bahasa.

James
sumber
0

Selama kinerja tidak terlalu penting bagi Anda, Anda selalu dapat menjalankannya di Brython yang secara efektif menempatkannya di kotak pasir JavaScript

Ian Besar
sumber