Skip to main content

Inappropriate coding practices - relative path command

Need

Enforcement of secure coding practices for file path handling

Context

  • Usage of Node.js v14.0.0 for server-side JavaScript development
  • Usage of Express for building web applications and APIs
  • Usage of child_process for executing external commands and managing child processes

Description

Non compliant code

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.

Steps

  • Replace the use of exec with execFile function from the child_process module.
  • Use absolute paths for calling executables instead of relying on relative paths.
  • Validate and sanitize the command input to prevent command injection attacks.

Compliant code

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.

References