Skip to main content

Inappropriate coding practices - relative path command

Need

Enforce secure coding practices to prevent the use of relative path commands

Context

  • Usage of C# 7.0 for modern language features and enhancements
  • Usage of Microsoft.AspNetCore.Mvc for building web applications with ASP.NET Core
  • Usage of Microsoft.AspNetCore.Hosting for hosting ASP.NET Core applications
  • Usage of System.Diagnostics for performance monitoring and debugging in .NET development
  • Usage of System.IO for input/output operations in .NET development

Description

Non compliant code

public class SampleController : Controller
{
private readonly IHostingEnvironment _env;

public SampleController(IHostingEnvironment env)
{
_env = env;
}

public ActionResult ExecuteCommand(string command)
{
var commandPath = Path.Combine(_env.ContentRootPath, command);
var processInfo = new ProcessStartInfo(commandPath)
{
UseShellExecute = false,
RedirectStandardOutput = true
};
var process = Process.Start(processInfo);
var output = process.StandardOutput.ReadToEnd();
process.WaitForExit();

return Content(output);
}
}

This piece of code is responsible for executing a command that is passed as a parameter to the ExecuteCommand action in the SampleController. The command is combined with the application's root path using Path.Combine to form a relative path. This path is then passed to a ProcessStartInfo object which is used to start a new process.

The vulnerability lies in the fact that the process is started with a command that is formed from a relative path. An attacker can manipulate the PATH environment variable to point to a directory that contains a malicious executable with the same name as the command. When the process is started, the operating system will search for the command in the directories listed in the PATH environment variable and execute the first match it finds.

This means that if an attacker can control the PATH environment variable and can predict or control the command that is passed to the ExecuteCommand action, they can cause the application to execute a malicious command. This can lead to a full system compromise.

This vulnerability can be mitigated by always using absolute paths when starting processes and by validating and sanitizing all input.

Steps

  • Avoid using user-supplied input directly in the command execution.
  • Validate and sanitize the input before using it in the command execution.
  • Use absolute paths instead of relative paths to reference executables.
  • Implement proper input validation to ensure that only allowed commands can be executed.
  • Consider using a whitelist approach to specify the allowed commands.
  • Implement proper error handling to handle any exceptions that may occur during the command execution.

Compliant code

public class SampleController : Controller
{
private readonly IHostingEnvironment _env;
private readonly List<string> allowedCommands = new List<string> { "command1", "command2" }; // Add your allowed commands here

public SampleController(IHostingEnvironment env)
{
_env = env;
}

public ActionResult ExecuteCommand(string command)
{
if (string.IsNullOrWhiteSpace(command) || !allowedCommands.Contains(command))
{
return BadRequest("Invalid command");
}

var commandPath = Path.Combine(_env.ContentRootPath, command);
if (!Path.IsPathRooted(commandPath))
{
return BadRequest("Command path must be absolute");
}

var processInfo = new ProcessStartInfo(commandPath)
{
UseShellExecute = false,
RedirectStandardOutput = true
};

try
{
using (var process = Process.Start(processInfo))
{
var output = process.StandardOutput.ReadToEnd();
process.WaitForExit();
return Content(output);
}
}
catch (Exception ex)
{
// Log the exception
return StatusCode(500, "An error occurred while executing the command");
}
}
}

The updated code includes several security improvements to mitigate the risk of command injection attacks:

  1. Input Validation: The code checks if the command is null, empty, or not in the list of allowed commands. If the command is invalid, the method returns a bad request response.

  2. Absolute Paths: The code checks if the command path is absolute. If the path is not absolute, the method returns a bad request response. This prevents an attacker from manipulating the PATH environment variable to execute arbitrary commands.

  3. Whitelist Approach: The code uses a whitelist approach to specify the allowed commands. This ensures that only the specified commands can be executed, reducing the attack surface.

  4. Error Handling: The code includes a try-catch block to handle any exceptions that may occur during the command execution. If an exception occurs, the method returns an internal server error response. This prevents the application from crashing and potentially revealing sensitive information to an attacker.

References