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__
dariexec
konteks untuk melarang penggunaan paket yang berpotensi berbahaya sepertios
. 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
exec
konteks, 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.NodeVisitor
untuk 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
PyPy
atau sesuatu yang mirip dengan sandbox kode.
CATATAN: Saya sadar bahwa setidaknya ada satu juru bahasa berbasis JavaScript. Itu tidak akan berfungsi dalam skenario saya.
sumber
Jawaban:
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:
Ned Batchelder dimulai dengan demonstrasi betapa berbahayanya
eval()
sebenarnya ;eval()
sering digunakan untuk mengeksekusi ekspresi Python; sebagai kotak pasir primitif dan naif untuk one-liners.Dia kemudian terus mencoba dan menerapkan prinsip yang sama pada Python 3 , akhirnya berhasil untuk keluar dengan beberapa petunjuk bermanfaat.
Pierre Bourdon menggunakan teknik serupa untuk meretas sistem python di hack-a-thon
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
exec
pernyataan (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 lokalos
di namespace modul Anda yang merujuk keos
modul. Ini dapat mengarahkan penyerang yang gigih ke modul yang dapat membantu mereka keluar dari kotak pasir. Thepickle
modul, misalnya, memungkinkan Anda memuat kode objek sewenang-wenang misalnya, jadi jika setiap jalan melalui modul daftar putih mengarah kepickle
modul, 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.
RestrictedPython
mengubah kode Python menjadi sesuatu yang memungkinkan Anda mengontrol nama, modul, dan objek apa yang diizinkan dalam Python 2.3 hingga 2.7.Jika
RestrictedPython
cukup 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.
sumber
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:
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.
sumber
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.
sumber
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.
sumber
Selama kinerja tidak terlalu penting bagi Anda, Anda selalu dapat menjalankannya di Brython yang secara efektif menempatkannya di kotak pasir JavaScript
sumber