Insecure or unset HTTP headers - CORS - Go

Insecure or unset HTTP headers - CORS - Go

Need

Enforcement of secure and specific HTTP headers for Cross-Origin Resource Sharing (CORS)

Context

  • Usage of Go 1.16 for developing high-performance and efficient applications
  • Usage of cors from github.com/gin-contrib for enabling Cross-Origin Resource Sharing (CORS) in a Gin framework application.
  • Usage of Gin framework for building web applications in Go

Description

Non compliant code

        package main

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

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

	config := cors.DefaultConfig()
	config.AllowAllOrigins = true

	r.Use(cors.New(config))

	r.GET("/endpoint", func(c *gin.Context) {
		c.JSON(200, gin.H{
			"message": "Hello World!",
		})
	})

	r.Run()
}
        
        

In this piece of code, we are setting up a simple server using the Gin framework in Go. We are also using the cors middleware provided by the gin-contrib package to handle Cross-Origin Resource Sharing (CORS).

The vulnerability lies in the following lines:

                config := cors.DefaultConfig()
config.AllowAllOrigins = true

            


Here, we are allowing all origins to access our server. This is done by setting AllowAllOrigins to true in the CORS configuration.

This is a security risk as it allows any website to make a request to our server, potentially exposing sensitive user data to malicious actors. It effectively means that the server has no control over who can interact with it, opening up potential for Cross-Site Scripting (XSS) or data injection attacks.

In a production environment, it is strongly recommended to specify only the trusted domains that should be allowed access. This can be done by setting AllowOrigins to an array of trusted domains, rather than allowing all origins.

Steps

  • Set the 'AllowAllOrigins' flag to false in the CORS configuration.
  • Specify the list of allowed origins explicitly instead of allowing all origins.
  • Remove the wildcard '*' from the list of allowed origins.
  • Configure the CORS middleware to only allow specific domains or origins.
  • Consider using a whitelist approach to allow only trusted domains.
  • Implement proper validation and sanitization of the 'Origin' header to prevent header injection attacks.
  • Ensure that the CORS configuration is applied to all relevant routes and endpoints in the application.

Compliant code

        package main

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

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

	config := cors.DefaultConfig()
	config.AllowAllOrigins = false
	config.AllowOrigins = []string{"http://example.com"}

	r.Use(cors.New(config))

	r.GET("/endpoint", func(c *gin.Context) {
		c.JSON(200, gin.H{
			"message": "Hello World!",
		})
	})

	r.Run()
}
        
        

The original code had a vulnerability where it allowed Cross-Origin Resource Sharing (CORS) from all origins. This is a security risk as it allows any domain to make requests to your server, potentially exposing sensitive information.

The fixed code sets the AllowAllOrigins flag to false in the CORS configuration. This means that not all domains are allowed to make requests to your server.

Instead of allowing all origins, we specify a list of allowed origins explicitly. In this case, only "http://example.com" is allowed. This is done by setting config.AllowOrigins to a slice containing the allowed origins.

The CORS middleware is configured to only allow specific domains or origins. This is a whitelist approach, where only trusted domains are allowed to make requests.

The CORS configuration is applied to all routes and endpoints in the application by using the r.Use(cors.New(config)) line. This ensures that the CORS policy is enforced consistently across the application.

By implementing these changes, we can prevent potential security risks associated with allowing all origins to make requests to our server.

References