Di masa lalu, ketika pengembangan web didasarkan pada kenyataan bahwa aplikasi server mengirim permintaan ke basis data relasional dan mengeluarkan output HTML, kode ini sering ditemukan:
atau semacamnya:
Sejak itu, kami telah belajar menggunakan pendekatan yang lebih aman.
Banyak digunakan adalah alat-alat seperti mesin template dan pengikatan parameter. Saat ini sangat jarang untuk menemukan rangkaian string yang berbahaya.
Pada artikel ini, saya ingin membagikan pemikiran saya tentang serangan dengan menyuntikkan kode. Tampaknya, mereka masih menjadi ancaman dalam JavaScript.

Untuk memahami alasannya, kami memecah salah satu contoh yang gagal menjadi fragmen yang lebih sederhana. Seperti ini:
function f(userInput: A): A { const firstCommand: A = ...; const secondCommand: A = ...; return firstCommand.concat(userInput.concat(secondCommand)); }
Jelas,
akar penyebab serangan dengan memperkenalkan kode adalah bahwa tidak ada perbedaan antara perintah dan input pengguna untuk komputer! Oleh karena itu, penyerang dapat memasukkan data yang akan diproses lebih lanjut sebagai kode.Tentu saja, seperti yang saya katakan, ada pertahanan terkenal terhadap serangan seperti itu. Alih-alih ini:
"SELECT name FROM users WHERE login = \"" + login + "\""
lebih baik menulis sesuatu seperti ini:
query("SELECT name FROM users WHERE login = :login", {login})
Dengan demikian,
SELECT name FROM users WHERE login =:login
perintah
SELECT name FROM users WHERE login =:login
jelas dipisahkan dari data
{login}
. Pada saat yang sama, mekanisme internal memastikan bahwa data disiapkan untuk digunakan dalam kueri SQL. Meloloskan kutipan dan menyuntikkan kode berbahaya akan gagal.
Namun, pengembangan aplikasi web sedang booming. Tidak hanya ini semakin banyak ditemukan:
{ paramA: "the value of the A parameter", paramB: "the value of the A parameter", }
tetapi juga ini:
{ paramA: "the value of the A parameter", paramB: {$in: [ "the value of the B parameter", "the value of the C parameter", ]}, }
Perbedaan signifikan antara kedua opsi adalah bahwa nilai parameter adalah objek yang menyertakan perintah!
Katakanlah nilai dibaca dari
userInput
:
{ paramA: userInput.paramA, paramB: {$in: [ userInput.paramB[0], userInput.paramB[1], ]}, }
Tidak perlu khawatir tentang pengguna yang menyediakan string jahat. Semuanya akan ditangani dengan cara yang aman.
Masalahnya adalah bahwa nilai-nilai parameter tidak hanya nilai-nilai sederhana seperti
the value of the A parameter
, tetapi juga perintah, misalnya
{$in: ["B", "C"]}
. Pengguna dapat mengirim permintaan dengan berbagai cara, setelah dekripsi objek diperoleh (form, JSON atau XML), dan oleh karena itu kode dapat diserang dengan injeksi.
Asumsikan
userInput.paramA
adalah
{$empty: false}
. Maka pertanyaannya adalah sebagai berikut:
{ paramA: {$empty: false}, paramB: {$in: [ userInput.paramB[0], userInput.paramB[1], ]}, }
Sekali lagi, ternyata untuk komputer, perintah yang dapat diandalkan tidak dapat dibedakan dari input pengguna yang tidak dapat diandalkan.
Hanya sekarang ini bukan tentang string yang dapat diandalkan dan tidak dapat diandalkan, tetapi tentang objek yang dapat diandalkan dan tidak dapat diandalkan.Untuk menghindari masalah ini, Anda harus selalu menulis perintah sehingga tidak dapat diterima dari pengguna. Ini dapat diwujudkan, antara lain, menggunakan pendekatan yang digunakan dalam
React dan
Snabbdom-Signature (ini adalah perpustakaan kecil untuk perlindungan terhadap injeksi ke DOM virtual), yaitu, menandai setiap objek perintah
Symbol
sehingga tidak dapat dikirim melalui jaringan.
Saya akui, saya sendiri sudah sering berpikir bahwa karena tidak ada database SQL atau jika saya menggunakan DOM virtual, serangan dengan menyuntikkan kode tidak mengancam saya. Betapa salahnya aku!
MENCARI. RUMAH - proyek ini mengumpulkan lebih dari 150 titik pandang kaca di 40 negara. Anda dapat dengan cepat menjalankan perintah host, ping, traceroute, dan mtr.
