Inappropriate coding practices - relative path command - Go

Inappropriate coding practices - relative path command - Go

Need

Enforcement of secure coding practices to prevent the use of relative path commands

Context

  • Usage of Go 1.15 for developing high-performance and efficient applications
  • Usage of gin-gonic/gin for building web applications in Go

Description

Non compliant code

        package main

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

func main() {
	r := gin.Default()
	r.GET("/run", func(c *gin.Context) {
		cmd := exec.Command("./someRelativePathCommand")
		_, err := cmd.Output()
		if err != nil {
			log.Fatal(err)
		}
		c.JSON(200, gin.H{
			"message": "Command executed",
		})
	})
	r.Run()
}
        
        

The above code represents a Go backend application using the Gin framework. The vulnerability lies in the GET request handler for the "/run" path.

Here, the exec.Command("./someRelativePathCommand") is used to run a command that is based on a relative path. This is a dangerous practice as it opens up the possibility for an attacker to manipulate the PATH environment variable to execute arbitrary commands.

In this case, an attacker could potentially manipulate the PATH to point to a directory containing a malicious executable named someRelativePathCommand. When the "/run" endpoint is hit, the server would then execute the malicious command, potentially leading to a complete system compromise.

Steps

  • Avoid using relative paths when executing external commands.
  • Use absolute paths instead to ensure the command is executed from the intended location.
  • Validate and sanitize any user input used in the command to prevent command injection attacks.
  • Consider using a whitelist approach to specify the allowed commands and their absolute paths.
  • Regularly update and patch the system to minimize the risk of compromised executables in the PATH.
  • Implement proper access controls and permissions to restrict the execution of commands to authorized users only.

Compliant code

        package main

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

func main() {
	r := gin.Default()
	r.GET("/run", func(c *gin.Context) {
		cmd := exec.Command("/absolute/path/to/someCommand")
		_, err := cmd.Output()
		if err != nil {
			log.Fatal(err)
		}
		c.JSON(200, gin.H{
			"message": "Command executed",
		})
	})
	r.Run()
}
        
        

The updated code now uses an absolute path when executing the external command. This ensures that the command is executed from the intended location, regardless of the current working directory or the state of the PATH environment variable.

The exec.Command function now takes an absolute path to the command as its argument. This path should be updated to the actual location of the command on your system.

Please note that this code does not include input validation or a whitelist approach for allowed commands. These are important security measures that should be implemented in a production environment.

Also, remember to regularly update and patch your system to minimize the risk of compromised executables in the PATH. Implement proper access controls and permissions to restrict the execution of commands to authorized users only.

References