flawopen.com/Command Injection/exec() vs execFile()
Apa perbedaan exec() dan execFile() di Node.js?
exec() menerima satu string dan menjalankannya melalui shell: pipe dan wildcard berfungsi, tetapi metakarakter shell dalam input tak tepercaya juga dapat mengubah perintah. execFile() menjalankan program yang ditentukan secara langsung dengan array argumen dan tanpa shell secara default. Ini mencegah parsing shell, tetapi tidak menghilangkan semua risiko: program tujuan masih dapat menafsirkan argumen sebagai opsi atau bertindak atas nilai yang tidak diharapkan.
Perbandingan
exec(`ls ${dir} | grep .txt`,
(err, out) => {...})
// pipe berfungsi, tetapi metakarakter juga berpengaruh.
execFile('ls', [dir],
(err, out) => {...})
// tanpa shell; validasi cara ls menafsirkan argumen dir.
// break out of its own argument
Saat fitur shell benar-benar diperlukan
Jika perintah benar-benar memerlukan pipe, ekspansi glob, atau pengalihan shell, execFile() tidak dapat menyatakannya secara langsung. Sebaiknya susun pipeline di Node.js dengan menjalankan setiap tahap secara terpisah dan menghubungkan stream. Jika exec() tidak dapat dihindari, jangan masukkan input tak tepercaya ke string perintah. Array argumen tanpa shell juga tidak mencegah argument injection: validasi setiap nilai sesuai program tujuan, gunakan -- jika didukung program tersebut, dan izinkan hanya perintah serta opsi yang diharapkan. Opsi shell: true mengaktifkan shell pada API yang biasanya tidak menggunakannya; jangan berikan input yang belum disanitasi dalam mode ini.
Pertanyaan umum
File batch Windows mengubah batas keamanan
Di Windows, file .bat dan .cmd tidak dapat dijalankan langsung dengan execFile(). Dokumentasi Node menjelaskan bahwa file tersebut dapat dipanggil melalui exec(), cmd.exe, atau spawn() dengan shell aktif; jalur ini mengembalikan parsing oleh command interpreter. Utamakan executable native atau API langsung. Jika pemanggilan file batch tidak dapat dihindari, tetapkan path skrip dan argumennya atau validasi sesuai kontrak skrip yang tepat. Node juga menandai penggunaan array argumen bersama shell: true sebagai deprecated (sejak v22.15.0 dan v23.11.0).
spawn() juga berjalan tanpa shell secara default dan menerima array argumen. Perbedaan praktis utamanya adalah penanganan output: spawn() mengalirkan output sebagai stream, sedangkan execFile() menyimpannya dalam buffer. Keduanya tidak mencegah program tujuan menafsirkan argumen sebagai opsi; validasi sesuai program tersebut. Menetapkan shell: true mengaktifkan kembali parsing shell.