Technical information leak - Headers - Go

Technical information leak - Headers - Go

Need

Prevention of technical information leakage through server response headers

Context

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

Description

Non compliant code

        package main

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

func main() {
    r := gin.Default()
    r.GET("/ping", func(c *gin.Context) {
        c.JSON(200, gin.H{
            "message": "pong",
        })
    })
    r.Run() // listen and serve on 0.0.0.0:8080 (for windows "localhost:8080")
}
        
        

In the above code, we're using the Gin web framework for Go to create a simple server that responds to GET requests at the "/ping" endpoint with a JSON message.

However, by default, the Gin framework includes some headers in the response that could potentially leak sensitive information. For instance, the Server header might reveal the name and version of the server software, while the X-Powered-By header could expose the technologies used by the server.

An attacker might use this information to identify potential vulnerabilities in the specific versions of the software or technologies that you're using, making your application a more attractive target for exploits.

Therefore, it's generally a good practice to remove or obfuscate these headers to reduce the amount of information that's available to potential attackers.

Steps

  • Disable or modify the default server response headers
  • Remove or modify any sensitive information in the response headers
  • Implement a custom middleware to handle response headers
  • Ensure that only necessary information is included in the response headers
  • Regularly update and patch the server and framework to address any known vulnerabilities

Compliant code

        package main

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

func SecureHeaders() gin.HandlerFunc {
	return func(c *gin.Context) {
		c.Header("Server", "Server")
		c.Header("X-Content-Type-Options", "nosniff")
		c.Header("X-Frame-Options", "SAMEORIGIN")
		c.Header("X-XSS-Protection", "1; mode=block")
		c.Next()
	}
}

func main() {
	r := gin.New()
	r.Use(SecureHeaders())
	r.GET("/ping", func(c *gin.Context) {
		c.JSON(200, gin.H{
			"message": "pong",
		})
	})
	r.Run() // listen and serve on 0.0.0.0:8080 (for windows "localhost:8080")
}
        
        

The original code was vulnerable because it was leaking technical information through the server response headers. This could potentially expose sensitive information such as technology names or component versions.

The fixed code includes a new middleware function SecureHeaders(). This function sets several security-related headers to prevent information leakage and other common web vulnerabilities:

- Server: This header is set to a generic value ("Server") to prevent revealing specific server software and version information.
- X-Content-Type-Options: This header is set to "nosniff" to prevent the browser from trying to interpret content differently from the declared content type.
- X-Frame-Options: This header is set to "SAMEORIGIN" to prevent clickjacking attacks by only allowing the page to be framed by pages from the same origin.
- X-XSS-Protection: This header is set to "1; mode=block" to enable XSS filtering. If a cross-site scripting attack is detected, the browser will sanitize the page (remove the unsafe parts).

The SecureHeaders() middleware is added to the Gin engine with r.Use(SecureHeaders()) before defining the routes. This ensures that the middleware is executed for every request, setting the secure headers before any response is sent.

References