Lack of data validation - Host Header Injection - Go

Lack of data validation - Host Header Injection - Go

Need

Implementation of proper input validation and sanitization for the host header

Context

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

Description

Non compliant code

        package main

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

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

	r.GET("/", func(c *gin.Context) {
		host := c.Request.Host
		c.Redirect(302, "http://"+host+"/malicious")
	})

	r.Run() // listen and serve on 0.0.0.0:8080 (for windows "localhost:8080")
}
        
        

In the above code, we have a simple Gin application with one route, /. This route retrieves the host from the incoming request with c.Request.Host and then redirects the client to a new URL that includes the original host in its structure.

The vulnerability lies in the fact that the Host header can be manipulated by an attacker. This means that the attacker can set the Host header to a malicious website, and the application will redirect the user to this malicious website.

This is a Host Header Injection vulnerability because the application uses user-supplied data (the Host header in the HTTP request) in the Location header of an HTTP response without validating it. This can lead to unintended behavior such as redirecting users to malicious websites.

The code does not validate or sanitize the Host header from the client's request before using it to construct the redirect URL, which means an attacker can manipulate the Host header to control the application's flow.

In this case, the application is vulnerable to phishing attacks, as an attacker can redirect users to a malicious site that looks like the original site but is controlled by the attacker. Users may then unwittingly provide sensitive information such as login credentials to the attacker.

Steps

  • Implement proper input validation for the host header.
  • Use a whitelist approach to validate the host header value.
  • Ensure that the host header value matches the expected domain or IP address.
  • Reject requests with host header values that contain unexpected characters or patterns.
  • Sanitize the host header value to remove any potentially malicious characters or sequences.
  • Consider using a secure redirect method, such as HTTP 307, instead of HTTP 302.
  • Regularly update and patch the Gin framework to benefit from security fixes and improvements.

Compliant code

        package main

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

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

	r.GET("/", func(c *gin.Context) {
		host := c.Request.Host
		// Validate the host header
		if isValidHost(host) {
			c.Redirect(307, "http://"+host+"/malicious")
		} else {
			c.String(400, "Invalid host header")
		}
	})

	r.Run() // listen and serve on 0.0.0.0:8080 (for windows "localhost:8080")
}

// Function to validate the host header
func isValidHost(host string) bool {
	// Add your whitelist of valid hosts here
	validHosts := []string{"localhost:8080", "example.com"}

	// Parse the host header
	parsedHost, err := url.Parse(host)
	if err != nil {
		return false
	}

	// Check if the host header is in the whitelist
	for _, validHost := range validHosts {
		if parsedHost.Host == validHost {
			return true
		}
	}

	return false
}
        
        

The updated code includes a function isValidHost that validates the host header against a whitelist of valid hosts. This function is called before the redirect is performed. If the host header is not valid, the function returns a 400 status code with the message "Invalid host header".

The redirect method has been changed from HTTP 302 to HTTP 307. HTTP 307 is a secure redirect method that does not allow the HTTP method to change during the redirect. This can help prevent certain types of attacks.

The isValidHost function uses the url.Parse function from the net/url package to parse the host header. This function returns an error if the host header is not a valid URL, which helps to sanitize the input and remove any potentially malicious characters or sequences.

The whitelist of valid hosts is defined in the validHosts slice. This should be updated to include the actual valid hosts for your application. The function checks if the parsed host header is in this whitelist, and only allows the redirect to proceed if it is.

This approach helps to ensure that the host header cannot be manipulated to cause unintended redirects to malicious websites.

References