OS Command Injection in Go Lang
Vulnerable example
Even though Go has native methods to execute external programs defined in the os/exec
package, it lacks a system
equivalent method that can be used to run shell scripts. A simple equivalent implementation could be the following:
func System(shell_command string) (string, error) {
cmd := exec.Command("/bin/sh", "-c", shell_command)
output, err := cmd.Output()
if err != nil {
return "", err
}
return string(output), nil
}
Care must be taken, however, because if the shell_command
variable is controlled by the user, it could introduce an OS Command Injection vulnerability.
Prevention
Since Go lacks a proper shell-escaping mechanism, the obvious solution, when applicable, is to refrain from using a proper shell invocation in favour of something that could be implemented using Go itself. The execution of external commands can be rendered more secure (provided, of course, that the usage command itself is safe) by using the exec.Command
method directly to invoke the desired command instead of invoking a system shell. In fact, by passing individual program arguments to this method, the argument injection is avoided. For example:
exec.Command("/usr/bin/nslookup", host)
In this case, whatever the value of host
is, it will always be passed as a single argument to nslookup
.
References
Mitre - CWE-78: Improper Neutralization of Special Elements used in an OS Command