Enforcement of secure coding practices for file path handling
import express from 'express';
import { exec } from 'child_process';
const app = express();
app.get('/execute', (req, res) => {
const command = req.query.command;
exec(command, (error, stdout, stderr) => {
if (error) {
console.error(`Error executing command: ${error.message}`);
return res.status(500).send('Error executing command');
}
console.log(`Command executed successfully: ${stdout}`);
res.send(stdout);
});
});
app.listen(3000, () => {
console.log('Server started on port 3000');
});
The vulnerability in this code lies in the use of the
exec
function from the
child_process
module without specifying an absolute path for the command being executed.
When a user sends a GET request to the
/execute
endpoint with a
command
query parameter, the code directly passes the
command
value to the
exec
function. This means that an attacker can manipulate the
command
parameter to execute arbitrary commands on the server.
By manipulating the
command
parameter, an attacker can potentially execute malicious commands that can compromise the system, as the
exec
function will look for the executable in the system's environment variables or PATH.
For example, if an attacker sends a request with the
command
parameter set to
rm -rf /
, it would attempt to execute the
rm
command with the
-rf /
argument, which would delete all files and directories on the server.
To mitigate this vulnerability, it is recommended to use absolute paths when calling executables. This ensures that the command is executed from a specific location and not dependent on the system's environment variables or PATH.
import express from 'express';
import { execFile } from 'child_process';
import { sanitizeCommand } from './utils';
const app = express();
app.get('/execute', (req, res) => {
const command = sanitizeCommand(req.query.command);
const executablePath = '/path/to/executable'; // Replace with the absolute path of the executable
execFile(executablePath, [command], (error, stdout, stderr) => {
if (error) {
console.error(`Error executing command: ${error.message}`);
return res.status(500).send('Error executing command');
}
console.log(`Command executed successfully: ${stdout}`);
res.send(stdout);
});
});
app.listen(3000, () => {
console.log('Server started on port 3000');
});
The fixed code addresses the vulnerability by using absolute paths for calling executables. Here's an explanation of the changes made:
1. The
execFile
function from the
child_process
module is imported to execute the command securely.
2. The
sanitizeCommand
function from the
./utils
module is imported to sanitize the command received from the user. This function ensures that any potentially malicious characters or commands are removed or escaped, preventing command injection attacks.
3. The
app.get('/execute')
route handles the GET request to execute a command. The command is obtained from the
req.query.command
parameter.
4. The
executablePath
variable is set to the absolute path of the executable. It is recommended to replace the placeholder
/path/to/executable
with the actual absolute path of the executable file.
5. The
execFile
function is called with the
executablePath
and the sanitized
command
as arguments. This ensures that the executable is called using an absolute path, mitigating the risk of an attacker manipulating the environment variables or PATH.
6. In case of an error executing the command, an error message is logged to the console, and a 500 status response with an error message is sent back to the client.
7. If the command is executed successfully, the output is logged to the console, and the output is sent back to the client as the response.
8. The server is started on port 3000, and a message is logged to the console indicating that the server has started.
By using absolute paths for calling executables and sanitizing user input, the fixed code ensures that the system is not vulnerable to the inappropriate coding practice of using relative path commands.