Skip to main content

OS Command Injection

Need

Prevention of OS command injection attacks

Context

  • Usage of Go 1.16 for building high-performance and scalable applications
  • Usage of gin-gonic/gin for building web applications in Go
  • Usage of os/exec for executing external commands in the operating system

Description

Non compliant code

package main

import (
"os/exec"
"github.com/gin-gonic/gin"
)

func main() {
r := gin.Default()
r.POST("/execute", func(c *gin.Context) {
command := c.PostForm("command")
cmd := exec.Command("/bin/sh", "-c", command)
output, err := cmd.Output()
if err != nil {
c.JSON(500, gin.H{
"message": "Error executing command",
})
return
}
c.JSON(200, gin.H{
"output": string(output),
})

})
r.Run()
}

In this code, the application is using the Gin framework to set up a POST route at /execute. The function associated with this route takes a command from the form data of the POST request and executes it directly using exec.Command.

The main problem here is that the command is taken directly from the user input and is not sanitized before being executed. This means that an attacker can send any command in the command field of the POST request, and the server will execute it. This is a classic example of an OS command injection vulnerability.

For example, an attacker could send a request with the command field set to rm -rf /, which would delete all files in the server's filesystem. They could also send a command to download and execute a malicious script, which could give them full control over the server.

This is a very serious vulnerability, as it allows an attacker to execute arbitrary commands on the server with the same privileges as the user running the server process. In the worst case, if the server process is running as root, this could lead to a full compromise of the server.

Steps

  • Validate and sanitize user input before executing any command
  • Use a safe method to execute commands, such as the 'exec.Command' function with proper arguments
  • Avoid using user input directly in the command execution
  • Implement input validation to restrict the allowed characters and prevent command injection
  • Implement output encoding to prevent any potential injection of malicious content in the response
  • Regularly update and patch the application and its dependencies to ensure the latest security fixes

Compliant code

package main

import (
"os/exec"
"github.com/gin-gonic/gin"
"net/url"
)

func main() {
r := gin.Default()
r.POST("/execute", func(c *gin.Context) {
command := c.PostForm("command")

// Validate and sanitize user input
safeCommand, err := url.QueryUnescape(command)
if err != nil {
c.JSON(500, gin.H{
"message": "Invalid command",
})
return
}

// Use a safe method to execute commands
cmd := exec.Command("/bin/sh", "-c", safeCommand)
output, err := cmd.Output()
if err != nil {
c.JSON(500, gin.H{
"message": "Error executing command",
})
return
}
c.JSON(200, gin.H{
"output": string(output),
})

})
r.Run()
}

The original code was vulnerable to OS Command Injection, as it was directly using user input to execute system commands. This could allow an attacker to inject malicious commands and escalate privileges, obtain or modify sensitive information stored in the machine.

The fixed code now includes a validation and sanitization step for user input. It uses the url.QueryUnescape function to decode any potentially harmful characters in the user input. This function will return an error if the input contains any invalid escape sequences, which we can use to detect and reject malicious input.

The exec.Command function is used to execute the command, which is a safe method as it does not use a shell. This means that shell features like variable substitution and command chaining are not available, reducing the attack surface.

The output of the command is returned as a JSON response. If there is an error executing the command, a 500 response is returned with a message indicating the error.

Regular updates and patches should be applied to the application and its dependencies to ensure the latest security fixes are in place.

References