Skip to main content

Technical information leak - Errors

Need

Prevention of technical information leaks and error exposure

Context

  • Usage of Go 1.14 for building high-performance and scalable applications
  • Usage of gin-gonic/gin for building web applications and APIs in Go
  • Usage of net/http for building HTTP servers in a Node.js application

Description

Non compliant code

package main

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

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

r.POST("/login", func(c *gin.Context) {
var json struct {
Username string `json:"username" binding:"required"`
Password string `json:"password" binding:"required"`
}

if err := c.ShouldBindJSON(&json); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}

if json.Username != "admin" || json.Password != "admin" {
c.JSON(http.StatusUnauthorized, gin.H{"error": "Incorrect Username or Password"})
return
}

c.JSON(http.StatusOK, gin.H{"message": "You are logged in"})
})

r.Run() // listen and serve on 0.0.0.0:8080
}

The above code is a simple login backend application using the Gin Gonic framework in Go. The /login endpoint accepts a POST request with a JSON body containing username and password fields.

The application is vulnerable to a technical information leak through error messages. If a request is malformed or missing required fields, the server throws an error and returns the error message to the client. For example, if the JSON body does not contain the username or password fields, the server responds with a 400 Bad Request status and the error message Key: 'username' Error:Field validation for 'username' failed on the 'required' tag or Key: 'password' Error:Field validation for 'password' failed on the 'required' tag respectively.

This behaviour can expose sensitive technical details about the server and the application, which can be exploited by attackers to gather information about the system and potentially find other vulnerabilities. For instance, an attacker can send requests with different malformed JSON bodies to the /login endpoint and observe the error messages to infer details about the server's validation logic.

Steps

  • Implement proper error handling to prevent sensitive information leakage.
  • Avoid returning detailed error messages in the response to the client.
  • Instead of returning specific error messages, provide a generic error message to the client.
  • Consider logging the detailed error messages on the server-side for debugging purposes.
  • Implement rate limiting or request throttling mechanisms to prevent abuse of the endpoints.
  • Validate and sanitize user input to prevent any unexpected behavior or attacks.
  • Consider implementing authentication and authorization mechanisms to protect sensitive endpoints.
  • Regularly update and patch the dependencies and frameworks used in the application to address any known vulnerabilities.

Compliant code

package main

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

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

// Implement rate limiting
r.Use(gin.Limit(1 << 14))

r.POST("/login", func(c *gin.Context) {
var json struct {
Username string `json:"username" binding:"required"`
Password string `json:"password" binding:"required"`
}

if err := c.ShouldBindJSON(&json); err != nil {
// Log the error on the server-side
log.Printf("Error: %s", err.Error())
// Return a generic error message
c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid request"})
return
}

if json.Username != "admin" || json.Password != "admin" {
// Log the error on the server-side
log.Printf("Error: Incorrect Username or Password")
// Return a generic error message
c.JSON(http.StatusUnauthorized, gin.H{"error": "Authentication failed"})
return
}

c.JSON(http.StatusOK, gin.H{"message": "You are logged in"})
})

r.Run() // listen and serve on 0.0.0.0:8080
}

The updated code includes several improvements to address the identified vulnerability:

  1. Rate Limiting: The gin.Limit middleware is used to limit the number of incoming requests. This helps to prevent abuse of the endpoints by sending massive requests.

  2. Error Handling: Instead of returning detailed error messages in the response to the client, a generic error message is returned. This prevents sensitive information leakage. The detailed error messages are logged on the server-side for debugging purposes.

  3. Input Validation: The ShouldBindJSON function is used to validate the user input. This helps to prevent any unexpected behavior or attacks.

  4. Authentication: The code checks if the username and password are correct. If not, a generic error message is returned and the detailed error message is logged on the server-side.

By implementing these improvements, the application becomes more secure and less prone to information leakage and abuse of the endpoints.

References