Fungsi f()
menggunakan eval()
(atau sesuatu yang berbahaya) dengan data yang saya buat dan simpan di local_file
dalam mesin yang menjalankan program saya:
import local_file
def f(str_to_eval):
# code....
# ....
eval(str_to_eval)
# ....
# ....
return None
a = f(local_file.some_str)
f()
aman untuk dijalankan karena string yang saya berikan padanya adalah milik saya.
Namun, jika saya memutuskan untuk menggunakannya untuk sesuatu yang tidak aman (mis. Input pengguna) hal-hal bisa jadi sangat salah . Juga, jika local_file
berhenti menjadi lokal maka itu akan membuat kerentanan karena saya perlu mempercayai mesin yang menyediakan file itu juga.
Bagaimana saya harus memastikan bahwa saya tidak pernah "lupa" bahwa fungsi ini tidak aman untuk digunakan (kecuali kriteria tertentu terpenuhi)?
Catatan: eval()
berbahaya dan biasanya bisa diganti dengan sesuatu yang aman.
python
vulnerabilities
Fermi paradox
sumber
sumber
Jawaban:
Tentukan jenis untuk menghias input "aman". Dalam fungsi Anda
f()
, nyatakan bahwa argumen memiliki tipe ini atau menimbulkan kesalahan. Cukup pintar untuk tidak pernah menentukan pintasandef g(x): return f(SafeInput(x))
.Contoh:
Meskipun ini dapat dengan mudah dielakkan, itu membuatnya lebih sulit untuk melakukannya secara tidak sengaja. Orang mungkin mengkritik semacam cek kejam, tetapi mereka akan melewatkan intinya. Karena
SafeInput
tipe ini hanya tipe data dan bukan kelas berorientasi objek yang dapat disubklasifikasikan, memeriksa identitas tipe dengantype(x) is SafeInput
lebih aman daripada memeriksa kompatibilitas tipeisinstance(x, SafeInput)
. Karena kami ingin menegakkan jenis tertentu, mengabaikan jenis eksplisit dan hanya melakukan pengetikan bebek secara implisit juga tidak memuaskan di sini. Python memiliki sistem tipe, jadi mari kita gunakan untuk menangkap kemungkinan kesalahan!sumber
assert
dihapus secara otomatis karena saya akan menggunakan kode python yang dioptimalkan. Sesuatu sepertiif ... : raise NotSafeInputError
itu akan dibutuhkan.eval()
ke metode aktifSafeInput
, sehingga Anda tidak memerlukan pemeriksaan tipe eksplisit. Berikan metode beberapa nama yang tidak digunakan di kelas Anda yang lain. Dengan begitu, Anda masih bisa mengejek semuanya untuk tujuan pengujian.eval
memiliki akses ke variabel lokal, mungkin kode tergantung pada bagaimana ia memutasi variabel. Dengan memindahkan eval ke metode lain, ia tidak lagi memiliki kemampuan untuk bermutasi variabel lokal.SafeInput
konstruktor mengambil nama / pegangan file lokal dan melakukan pembacaan sendiri, memastikan bahwa data memang berasal dari file lokal.Seperti yang pernah ditunjukkan Joel, buat kode yang salah terlihat salah (gulir ke bawah ke bagian "Solusi Nyata", atau lebih baik baca sepenuhnya; itu sepadan, bahkan jika itu alamat variabel daripada nama fungsi). Jadi saya dengan rendah hati menyarankan untuk mengubah nama fungsi Anda menjadi sesuatu seperti
f_unsafe_for_external_use()
- Anda kemungkinan besar akan datang dengan beberapa skema singkatan sendiri.Sunting: Saya pikir saran amon adalah variasi OO berdasarkan tema yang sangat bagus :-)
sumber
Melengkapi saran oleh @amon, Anda juga dapat berpikir tentang menggabungkan pola strategi di sini, serta pola objek metode.
Dan kemudian implementasi 'normal'
Dan implementasi admin-input-eval
(Catatan: dengan contoh dunia nyata, saya mungkin bisa memberikan contoh yang lebih baik).
sumber