Dalam artikel ini, kita akan belajar cara memanggil perintah sistem dengan benar menggunakan Node.js untuk menghindari kerentanan injeksi baris perintah umum.
Metode yang sering kita gunakan untuk memanggil perintah adalah child_process.exec paling sederhana. Ini memiliki pola penggunaan yang sangat sederhana; Ini melewati perintah string dan mengembalikan hasil kesalahan atau pemrosesan perintah ke fungsi callback.
Berikut adalah contoh yang sangat khas dari perintah sistem panggilan Anda melalui Child_process.exec.
Salinan kode adalah sebagai berikut:
child_process.exec ('ls', function (err, data) {
console.log (data);
});
Namun, apa yang terjadi ketika Anda perlu menambahkan beberapa parameter yang dimasukkan pengguna ke perintah yang Anda hubungi? Solusi yang jelas adalah untuk mengikat input pengguna secara langsung dengan perintah Anda. Namun, pengalaman bertahun -tahun saya memberi tahu saya: ketika Anda mengirim string yang terhubung dari satu sistem ke sistem lain, akan ada masalah suatu hari nanti.
Salinan kode adalah sebagai berikut:
var path = "input pengguna";
child_process.exec ('ls -l' + path, function (err, data) {
console.log (data);
});
Mengapa string koneksi memiliki masalah?
Nah, karena di bawah mesin Child_Process.exec, eksekusi "/bin/sh" akan dipanggil. Bukan program target. Perintah yang dikirim baru saja diteruskan ke proses "/bin/sh 'baru untuk menjalankan shell. Nama Child_process.exec agak menyesatkan - ini adalah penafsir bash, bukan program. Ini berarti bahwa semua karakter shell dapat memiliki konsekuensi yang menghancurkan jika parameter yang dimasukkan oleh pengguna dieksekusi secara langsung.
Salinan kode adalah sebagai berikut:
[pid 25170] execve ("/bin/sh", ["/bin/sh", "-c", "ls -l input pengguna"], [/ * 16 vars */]
Misalnya, penyerang bisa menggunakan titik koma ";" Untuk mengakhiri perintah dan memulai panggilan baru, dan mereka dapat menggunakan backticks atau $ () untuk menjalankan sub -perintah. Ada juga banyak pelanggaran potensial.
Jadi apa cara yang benar untuk menyebutnya?
ExecFile / Spawn
Spawn dan ExecFile Ambil parameter array tambahan, yang bukan lingkungan shell yang dapat menjalankan perintah lain dan tidak akan menjalankan perintah tambahan.
Mari kita gunakan ExecFile dan Spawn untuk memodifikasi contoh sebelumnya untuk melihat bagaimana panggilan sistem berbeda dan mengapa tidak rentan terhadap injeksi perintah.
child_process.execfile
Salinan kode adalah sebagai berikut:
var child_process = membutuhkan ('child_process');
var path = "."
child_process.execfile ('/bin/ls', ['-l', path], fungsi (err, hasil) {
Console.log (hasil)
});
Menjalankan panggilan sistem
Salinan kode adalah sebagai berikut:
[pid 25565] execve ("/bin/ls", ["/bin/ls", "-l", "."], [/ * 16 VARS */]
child_process.spawn
Contoh penggunaan penggantian spawn sangat mirip.
Salinan kode adalah sebagai berikut:
var child_process = membutuhkan ('child_process');
var path = "."
var ls = child_process.spawn ('/bin/ls', ['-l', path])
ls.stdout.on ('data', fungsi (data) {
console.log (data.tostring ());
});
Menjalankan panggilan sistem
Salinan kode adalah sebagai berikut:
[pid 26883] execve ("/bin/ls", ["/bin/ls", "-l", "."], [/ * 16 vars */
Saat menggunakan Spawn atau ExecFile, tujuan kami adalah hanya menjalankan satu perintah (parameter). Ini berarti bahwa pengguna tidak dapat menjalankan perintah yang disuntikkan karena /bin /ls tidak tahu cara menangani backtick atau pipa atau;. Apa yang akan dijelaskannya /Bin /Bash adalah parameter dari perintah tersebut. Ini mirip dengan menggunakan parameter untuk meneruskan parameter ke dalam kueri SQL, jika Anda terbiasa dengannya.
Tetapi ada juga peringatan: menggunakan Spawn atau ExecFile tidak selalu aman. Misalnya, menjalankan /bin /menemukan dan meneruskan parameter input pengguna masih dapat menyebabkan sistem terperangkap. Perintah Temukan memiliki beberapa opsi yang memungkinkan membaca/menulis file sewenang -wenang.
Jadi, berikut adalah beberapa panduan tentang Node.js Running System Commands:
Hindari menggunakan child_process.exec, terutama ketika Anda perlu memasukkan parameter yang dimasukkan oleh pengguna, harap diingat.
Cobalah untuk menghindari membiarkan pengguna meneruskan parameter. Menggunakan pilihan jauh lebih baik daripada meminta pengguna memasukkan string secara langsung.
Jika Anda harus mengizinkan pengguna untuk memasukkan parameter, lihat parameter perintah secara luas, tentukan opsi mana yang aman, dan buat daftar putih.