Log injection - Go

Log injection - Go

Need

Secure logging mechanism

Context

  • Usage of Go 1.16 for building scalable and efficient applications
  • Usage of gin-gonic/gin for building web applications and APIs in Go
  • Usage of log for logging and debugging purposes
  • Usage of os for accessing operating system-related information and functionalities

Description

Non compliant code

        package main

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

func main() {
	router := gin.Default()

	router.GET("/log", func(c *gin.Context) {
		userInput := c.Query("userInput")
		logFile, _ := os.OpenFile("logFile.log", os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666)
		log.SetOutput(logFile)
		log.Println(userInput)
		c.JSON(200, gin.H{
			"message": "Log added",
		})
	})

	router.Run(":8080")
}
        
        

The above code is a simple Go application using the Gin framework that logs user input from a GET request into a log file. The vulnerability lies in the fact that it directly logs the user input without any form of validation, sanitization, or escaping.

When the "/log" endpoint is hit with a GET request, the application takes the user input from the query parameter "userInput" and logs it directly into a file "logFile.log".

The problem here is that if an attacker provides malicious input, it will be logged directly into the log file. This can lead to log injection attacks where an attacker can forge log entries or inject malicious scripts that can be executed when the log file is viewed or processed.

For example, an attacker could send a request like GET /log?userInput=malicious_script and the malicious script would be logged into the log file. This can lead to serious security issues like data breaches, execution of arbitrary code, or even complete system compromise if the log file is processed or viewed in an unsafe manner.

Steps

  • Validate and sanitize the user input before logging it
  • Use a logging library that automatically escapes special characters in the log entries
  • Implement proper input validation and filtering to prevent log injection attacks
  • Consider using a whitelist approach to only allow specific characters or patterns in the user input
  • Avoid logging sensitive information that could be exploited by an attacker

Compliant code

        package main

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

func main() {
	router := gin.Default()

	router.GET("/log", func(c *gin.Context) {
		userInput := c.Query("userInput")
		logFile, _ := os.OpenFile("logFile.log", os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666)
		log.SetOutput(logFile)

		// Validate and sanitize the user input
		validInput := sanitizeInput(userInput)

		log.Println(validInput)
		c.JSON(200, gin.H{
			"message": "Log added",
		})
	})

	router.Run(":8080")
}

func sanitizeInput(input string) string {
	// URL encode the input to escape special characters
	encodedInput := url.QueryEscape(input)

	// Use a whitelist approach to only allow specific characters or patterns
	// Here we are allowing only alphanumeric characters and spaces
	reg, _ := regexp.Compile("[^a-zA-Z0-9 ]+")
	safeInput := reg.ReplaceAllString(encodedInput, "")

	return safeInput
}
        
        

The updated code includes a function sanitizeInput that is used to sanitize the user input before it is logged. This function performs two main tasks:

1. URL encoding the input: This is done using the url.QueryEscape function, which will escape any special characters in the input string. This helps to prevent log injection attacks as any special characters that could be used to manipulate the log entries are escaped.

2. Whitelisting allowed characters: After URL encoding the input, a regular expression is used to remove any characters that are not alphanumeric or spaces. This is a whitelist approach where only specific characters or patterns are allowed in the user input. This further helps to prevent log injection attacks as it limits the characters that can be used in the user input.

By sanitizing the user input in this way, the system is protected against log injection attacks. It is also important to note that sensitive information should not be logged as it could be exploited by an attacker.

References