Link Search Menu Expand Document

OS Command Injection in Go Lang

Play SecureFlag Play Go Lang Labs on this vulnerability with SecureFlag!

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

OWASP - Command Injection