Prevention of OS command injection attacks
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.
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.