Lack of data validation - Emails - Go

Lack of data validation - Emails - Go

Need

Implementation of email validation to prevent registration with disposable email addresses

Context

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

Description

Non compliant code

        package main

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

type User struct {
	Email string `json:"email"`
}

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

	r.POST("/register", func(c *gin.Context) {
		var newUser User
		if err := c.ShouldBindJSON(&newUser); err != nil {
			c.JSON(400, gin.H{"error": err.Error()})
			return
		}

		// Registration logic here
		// ...

		c.JSON(200, gin.H{"message": "Registration successful"})
	})
	r.Run()
}
        
        

In this code, we have a simple Gin application in Go. The application has a single route /register which accepts POST requests for user registration. The request should contain a JSON payload with the email field.

The vulnerability lies in the fact that there is no validation performed on the email field of the incoming request in the /register route. The application accepts any string as an email, including those from disposable mailboxes such as yopmail.

This could lead to a variety of issues, including but not limited to:

1. Users registering with disposable emails and then abandoning them, leading to unverifiable user accounts. 2. Users using disposable emails to bypass email verification and perform malicious activities. 3. Increased spam accounts as disposable emails provide an easy way to create multiple accounts.

The lack of validation on the email field is the root cause of this vulnerability.

Steps

  • Implement email validation to ensure that the email provided is in a valid format.
  • Use a third-party email validation service or library to check if the email domain is disposable or belongs to a known disposable email provider.
  • Consider implementing a whitelist of allowed email domains to restrict registration to specific domains.
  • Provide clear error messages to the user when a disposable email is detected, indicating that they need to provide a valid email address.
  • Consider implementing rate limiting or CAPTCHA to prevent abuse of the registration endpoint by automated scripts.

Compliant code

        package main

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

type User struct {
	Email string `json:"email"`
}

var disposableDomains = []string{
	"yopmail.com",
	// Add more disposable email domains here
}

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

	r.POST("/register", func(c *gin.Context) {
		var newUser User
		if err := c.ShouldBindJSON(&newUser); err != nil {
			c.JSON(400, gin.H{"error": err.Error()})
			return
		}

		// Validate email
		if !isValidEmail(newUser.Email) {
			c.JSON(400, gin.H{"error": "Invalid email address"})
			return
		}

		// Registration logic here
		// ...

		c.JSON(200, gin.H{"message": "Registration successful"})
	})
	r.Run()
}

func isValidEmail(email string) bool {
	// Check if email is in valid format
	at := strings.LastIndex(email, "@")
	if at <= 0 || at+1 >= len(email) {
		return false
	}

	// Check if email domain is disposable
	domain := email[at+1:]
	if isDisposableDomain(domain) {
		return false
	}

	return true
}

func isDisposableDomain(domain string) bool {
	for _, disposableDomain := range disposableDomains {
		if domain == disposableDomain {
			return true
		}
	}
	return false
}
        
        

The updated code includes a function isValidEmail that checks if the email provided by the user is in a valid format and does not belong to a disposable email domain. The function isDisposableDomain checks if the domain of the email is in the list of disposable email domains.

The POST /register endpoint now validates the email before proceeding with the registration logic. If the email is not valid, it responds with a 400 status code and an error message "Invalid email address".

The list of disposable email domains is currently hardcoded in the disposableDomains variable. This list can be expanded as needed or replaced with a more sophisticated check, such as a call to a third-party email validation service.

This solution helps prevent users from registering with disposable email addresses, which can be used to bypass email verification, spam the system, or evade bans or restrictions based on the email address.

References