Insecure Use of Dangerous Function
This vulnerability category covers the following issues:
Command Injection
Why is this important?
Go, like any other programming language, has dangerous functions. If these functions are not used properly, it can have a catastrophic impact on your app. Go offers several ways to execute operating system commands, such as:
exec.Command()
exec.CommandContext()
syscall.Exec()
Attacker controlled input that is processed by any of these functions, can lead to attackers getting full access to your production environment.
Check out this video for a high-level explanation:
Read below to find out how to fix this issue in your code.
Fixing Insecure Use of Dangerous Function
Option A: Use the dangerous function securely
- Go through the issues that GuardRails identified in the PR.
- Locate the dangerous function. For example:
binary, lookErr := exec.LookPath("sh")
if lookErr != nil {
panic(lookErr)
}
env := os.Environ()
// This is the dangerous call taking user input
// and passing it to the operating system.
// To illustrate this example, assume that the form parameter name
// is expected to be `echo first name`.
// This would allow a malicious user to execute arbitrary commands.
args := []string{"sh", "-c", req.FormValue("name")}
execErr := syscall.Exec(binary, args, env)
if execErr != nil {
panic(execErr)
}
- Replace the dangerous function with the following:
// Golang is good at safely using arguments passed to commands.
// The key point is that the user input must not be able to control
// the actual command being executed. Which was shown in the example above.
// Instead of using `sh`, it's better to use the actual command.
// In our example from above, this would be the command `echo`.
// Alternatively, a white list of allowed commands can be defined and
// referenced to define the executable binary.
binary, lookErr := exec.LookPath("echo")
if lookErr != nil {
panic(lookErr)
}
env := os.Environ()
// This is the dangerous call taking user input
// and passing it to the operating system.
args := []string{"echo", req.FormValue("name")}
execErr := syscall.Exec(binary, args, env)
if execErr != nil {
panic(execErr)
}
- Test it and ensure the functionality works as expected
- Ship it 🚢 and relax 🌴