Automatic information enumeration - Credit Cards - Go

Automatic information enumeration - Credit Cards - Go

Need

Enhancement of credit card validation and security measures

Context

  • Usage of Go 1.16 for building efficient and scalable applications
  • Usage of gin-gonic/gin for building web applications in Go
  • Usage of net/http for creating a web server in a Node.js application

Description

Non compliant code

        package main

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

type CreditCard struct {
	Number        string `json:"number"`
	Expiration    string `json:"expiration"`
	SecurityCode  string `json:"securityCode"`
}

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

	r.POST("/creditCard", func(c *gin.Context) {
		var creditCard CreditCard
		if err := c.ShouldBindJSON(&creditCard); err != nil {
			c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
			return
		}

		// Here we should validate the credit card data but we are not doing it
		c.JSON(http.StatusOK, gin.H{"message": "Credit card registered successfully"})
	})

	r.Run()
}
        
        

The above code represents a simple HTTP server using the Gin framework in Go. This server has an endpoint /creditCard that accepts POST requests. The request body should contain a JSON representation of a credit card, including its number, expiration date, and security code.

The vulnerability lies in the fact that the server does not perform any validation on the received credit card data. This means that an attacker could potentially send a large number of requests with different credit card numbers, and the server would accept them all without checking if the expiration date is valid or if the security code is correct. This could lead to an information enumeration vulnerability, where an attacker could potentially discover valid credit card numbers by trying a large number of possibilities.

In real-world applications, not validating these fields could also lead to other issues such as storing invalid data in the database or attempting to charge a credit card that has already expired.

Steps

  • Implement validation for credit card number, expiration date, and security code.
  • Use a reliable credit card validation library or algorithm to ensure the credit card number is valid.
  • Validate the expiration date to ensure it is a future date and in the correct format.
  • Implement a validation algorithm or use a library to validate the security code.
  • Return an appropriate error response if any of the credit card data fails validation.

Compliant code

        package main

import (
	"github.com/gin-gonic/gin"
	"net/http"
	"time"
	"github.com/buckhx/durafmt"
	"github.com/jessevdk/go-validators"
)

type CreditCard struct {
	Number        string `json:"number" binding:"creditcard"`
	Expiration    string `json:"expiration" binding:"required,datetime=2006-01-02"`
	SecurityCode  string `json:"securityCode" binding:"numeric,length=3|4"`
}

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

	r.POST("/creditCard", func(c *gin.Context) {
		var creditCard CreditCard
		if err := c.ShouldBindJSON(&creditCard); err != nil {
			c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
			return
		}

		// Validate the expiration date
		expiration, err := time.Parse("2006-01-02", creditCard.Expiration)
		if err != nil {
			c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid expiration date"})
			return
		}

		if expiration.Before(time.Now()) {
			c.JSON(http.StatusBadRequest, gin.H{"error": "Expired credit card"})
			return
		}

		c.JSON(http.StatusOK, gin.H{"message": "Credit card registered successfully"})
	})

	r.Run()
}
        
        

The updated code now includes validation for the credit card number, expiration date, and security code.

- The binding:"creditcard" tag in the CreditCard struct ensures that the credit card number is valid using the go-validators library.
- The binding:"required,datetime=2006-01-02" tag ensures that the expiration date is provided and is in the correct format.
- The binding:"numeric,length=3|4" tag ensures that the security code is numeric and is either 3 or 4 digits long.

In the POST handler, we parse the expiration date and check if it is before the current date. If it is, we return an error response indicating that the credit card is expired.

This way, we ensure that all credit card data is valid before proceeding, thus preventing automatic information enumeration.

References