


























Command injection vulnerabilities are a severe security threat in Node.js applications. They arise when user-controlled input is used to construct system commands, allowing attackers to execute arbitrary code on your server.
Here, we explore secure coding practices to prevent such vulnerabilities and analyze real-world examples (CVE-2024-21488, CVE-2019-25158 as a couple of recent examples and reference points) to understand the risks and mitigation strategies.
child_process.execFile: This function executes a specific binary file, providing a safer alternative to child_process.exec as it avoids shell interpretation of arguments.
const { execFile } = require('child_process');
const filePath = 'path/to/safe_script.sh';
const args = ['argument1', 'argument2'];
execFile(filePath, args, (error, stdout, stderr) => {
// handle results
});
child_process.spawn: This function offers more granular control over command execution, allowing separate arguments and environment variable specification.
const { spawn } = require('child_process');
const command = 'ls';
const args = ['-l', '/tmp'];
const childProcess = spawn(command, args);
childProcess.stdout.on('data', (data) => {
console.log(`stdout: ${data}`);
});
childProcess.stderr.on('data', (data) => {
console.error(`stderr: ${data}`);
});
childProcess.on('close', (code) => {
console.log(`child process exited with code ${code}`);
});
child_process.exec: This function executes a shell command and is vulnerable to injection if user input is directly included in the command string. Avoid using child_process.exec unless absolutely necessary.
Construct commands as separate strings from user input and arguments. This prevents malicious code injection through manipulation of spaces or special characters.
// Sanitize user input
const sanitizedUserInput = sanitizeUserInput(userInput);
// Prepare user input to be escaped via command line arguments
// ❌ Insecure: Directly concatenating user input
const safeCommand = `some_command ${sanitizedUserInput}`;
// ✅ Secure: Using separate arguments
const safeCommand = child_process.execFile('some_command', [ '--someFlag', sanitizedUserInput]);
If possible, avoid using a shell environment when spawning child processes. This reduces the risk of shell interpretation issues.
const { spawn } = require('child_process');
spawn('ls', ['-l', '/tmp']);
When spawning child processes, consider overriding environment variables to prevent leaking sensitive information from your parent process environment.
const { spawn } = require('child_process');
// Override sensitive variable
const env = { ...process.env, MY_SECRET: 'redacted' };
spawn('some_command', [], { env });
The provided CVEs illustrate the consequences of insecure coding practices:
CVE-2024-21488: The network package uses child_process.exec without proper input sanitization, allowing attackers to inject arbitrary commands through user input.
CVE-2019-25158: The tts-api package is vulnerable to command injection via the onSpeechDone function due to potentially unsafe usage of shell commands.
By adopting secure coding practices and avoiding vulnerable APIs like child_process.exec, you can significantly reduce the risk of command injection vulnerabilities in your Node.js applications.
Stay updated on best practices and consider using libraries with a strong focus on secure coding principles.
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。