logo

Lack of data validation - Emails - Go


Need

Implementation of email validation to prevent registration with disposable email addresses


Context

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

Description

Insecure Code Example

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

  1. Implement email validation to ensure that the email provided is in a valid format.
  2. 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.
  3. Consider implementing a whitelist of allowed email domains to restrict registration to specific domains.
  4. Provide clear error messages to the user when a disposable email is detected, indicating that they need to provide a valid email address.
  5. Consider implementing rate limiting or CAPTCHA to prevent abuse of the registration endpoint by automated scripts.

Secure Code Example

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

  • 199 - Lack of data validation - Emails

  • Last updated

    2023/09/18