Sebuah platform pembelajaran yang membolehkan pelajar membina pertanyaan MongoDB telah menggugurkan modul vm Node.js dan kini menganalisis setiap pertanyaan ke dalam pokok sintaks abstrak (AST) sebelum pelaksanaan. Perubahan ini menghapuskan sandbox yang boleh diceroboh, sekali gus melindungi bahagian belakang (backend) daripada kod sewenang-wenangnya yang boleh disuntik melalui rentetan yang tidak sah.
Mengapa sandbox asal gagal
Implementasi pertama membungkus pemegang (handle) pangkalan data aktif dalam panggilan vm.runInContext dan cuba mengehadkan pengguna dengan ekspresi nalar (regular expression). Ia hanya membenarkan nama kaedah seperti find atau aggregate; setiap pengenal pasti yang lain sepatutnya ditapis keluar.
Dua kelemahan menjadikan pendekatan tersebut tidak selamat:
- Penapisan regex boleh dipintas. JavaScript membenarkan kod menggunakan notasi kurungan (
obj["constructor"]) untuk mencapai mana-mana harta (property). Penyerang boleh mendapatkan pembina (constructor)Function, membina fungsi baharu, dan menjalankan sebarang kod yang mereka mahu. Regex tidak akan melihat akses harta yang mendasari kerana sumbernya boleh ditulis semula dalam pelbagai cara. vmbukan sempadan keselamatan. Dokumentasi Node menyatakan bahawavmmengasingkan objek global tetapi bukan keseluruhan proses. Dengan menyuntik sambungan pangkalan data aktif ke dalam sandbox, kod di dalam konteks tersebut mengekalkan keupayaan untuk memanggil sebarang kaedah pada sambungan itu, termasuk kaedah yang menulis atau memadam data. Sandbox tersebut tidak menghalang kod daripada menjejaskan proses hos.
Penyelesaian berasaskan AST
Pasukan tersebut menggantikan pelaksanaan kod dengan analisis statik. Rentetan pertanyaan kini disalurkan ke penganalisis acorn, yang menghasilkan AST—satu representasi pokok bagi struktur sintaks kod. AST diperiksa nod demi nod berpandukan senarai putih (whitelist) yang ketat:
- Literal, tatasusunan dan objek hanya dibenarkan apabila ia muncul sebagai nilai biasa.
- Panggilan kaedah dihadkan kepada set yang telah ditetapkan (
find,sort,limit, dll.). Sebarang panggilan lain akan ditolak. - Akses harta dikira (contohnya,
obj[expr]) atau sebarang jenis nod yang tidak disenaraikan secara eksplisit akan mencetuskan kegagalan serta-merta.
Oleh kerana penganalisis berfungsi pada pokok, bukannya teks mentah, ia tidak boleh ditipu oleh ejaan alternatif atau helah notasi kurungan. Rantaian pembina yang sepatutnya terlepas daripada regex akan muncul sebagai nod yang tidak dikenali dan ditolak sebelum sebarang kod dijalankan.
Apa maksudnya untuk keselamatan
Reka bentuk baharu ini mengikut falsafah "tolak secara lalai" (deny by default):
- Tentukan apa yang dibenarkan, bukan apa yang dilarang. Senarai putih tekstual tidak boleh menyeluruh; AST mempunyai set jenis nod yang terhad, menjadikan pemeriksaan menyeluruh lebih praktikal.
- Jangan sesekali mendedahkan sumber aktif di dalam sandbox. Menghantar pemegang pangkalan data ke dalam konteks yang diasingkan memberikan kod sandbox akses terus ke bahagian belakang. Pendekatan penganalisis tidak pernah menyerahkan objek aktif kepada kod pengguna; ia hanya mengekstrak niat pertanyaan tersebut.
- Sahkan struktur, kemudian laksanakan dengan selamat. Sebaik sahaja AST melepasi pengesahan, platform akan menterjemah panggilan yang dibenarkan kepada kaedah pemacu MongoDB yang sebenar menggunakan laluan kod dipercayainya sendiri.
Apa yang perlu diperhatikan seterusnya
- Audit sebarang penggunaan
eval,new Function, atauvmdalam kod anda. Walaupun senarai putih boleh dipintas oleh sifat dinamik JavaScript. - Gunakan penganalisisan AST untuk kod yang dijana pengguna di mana-mana yang boleh. Pustaka seperti
acorn,esprima, ataubabel-parsermemudahkan transformasi tersebut. - Hadkan pendedahan objek aktif. Jika sambungan pangkalan data, pemegang fail, atau soket rangkaian perlu dicapai, bungkus ia dalam proksi yang hanya mendedahkan kaedah minimum yang anda ingin benarkan.
- Automasikan ujian kes pinggiran (edge cases). Jana pertanyaan yang menggunakan notasi kurungan, kunci dikira, atau manipulasi prototaip untuk mengesahkan penganalisis anda menolaknya.
Kesimpulan
Bergantung kepada vm.runInContext sebagai sandbox memberikan rasa selamat yang palsu; penapis regex tidak dapat merangkumi sintaks JavaScript yang fleksibel, dan sandbox tidak mengasingkan sumber proses. Menganalisis input pengguna ke dalam AST dan menyenarai putih hanya nod yang anda fahami menyediakan penghalang konkrit dan mudah diselenggara yang menghentikan kod berniat jahat sebelum ia dijalankan. Jika platform anda membenarkan pengguna menulis kod, gantikan pelaksanaan gaya eval dengan analisis statik hari ini.
