Skip to main content

Lack of protection against brute force attacks

Need

Implementation of strong and effective brute force protection mechanisms

Context

  • Usage of Go 1.16 for developing scalable 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"
)

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

r.POST("/login", func(c *gin.Context) {
username := c.PostForm("username")
password := c.PostForm("password")

if checkCredentials(username, password) {
c.JSON(200, gin.H{
"message": "Login successful",
})
} else {
c.JSON(401, gin.H{
"message": "Invalid credentials",
})
}
})

r.Run()
}

func checkCredentials(username string, password string) bool {
// This is just a placeholder function. In a real application, this would check the database.
return username == "admin" && password == "password"
}

The above code represents a simple login endpoint in a Gin application. When a POST request is sent to "/login", the username and password parameters are extracted from the request body. These credentials are then checked against a simple function checkCredentials which in this case just checks if the username is "admin" and the password is "password".

The vulnerability here lies in the fact that there is no protection against brute force attacks. An attacker can continuously send requests with different combinations of usernames and passwords until they find a combination that works. Since there is no rate limiting or account lockout after a certain number of failed attempts, the system is open to brute force attacks.

Steps

  • Implement rate limiting to prevent multiple login attempts within a short period of time.
  • Use strong and complex passwords to make it harder for brute force attacks to guess the credentials.
  • Implement account lockout mechanism after a certain number of failed login attempts to prevent further guessing.
  • Consider implementing CAPTCHA or other challenge-response mechanisms to differentiate between human and automated login attempts.
  • Implement two-factor authentication to add an extra layer of security to the login process.
  • Regularly monitor and analyze login logs to detect any suspicious login patterns or brute force attempts.
  • Educate users about the importance of using strong passwords and avoiding password reuse.
  • Regularly update and patch the application and its dependencies to fix any security vulnerabilities that could be exploited for brute force attacks.

Compliant code

package main

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

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

// Create a limiter struct.
limiter := tollbooth.NewLimiter(1, nil)

r.POST("/login", tollbooth_gin.LimitHandler(limiter), func(c *gin.Context) {
username := c.PostForm("username")
password := c.PostForm("password")

if checkCredentials(username, password) {
c.JSON(200, gin.H{
"message": "Login successful",
})
} else {
c.JSON(401, gin.H{
"message": "Invalid credentials",
})
}
})

r.Run()
}

func checkCredentials(username string, password string) bool {
// This is just a placeholder function. In a real application, this would check the database.
return username == "admin" && password == "password"
}

The updated code now includes a rate limiter to protect against brute force attacks. The rate limiter is set to allow only 1 request per second. This is done using the tollbooth library, which provides rate limiting and throttling capabilities.

In the main function, a new limiter is created with a maximum of 1 request per second. This limiter is then passed as a middleware to the /login route handler. This means that any requests to the /login route will first pass through the rate limiter before reaching the route handler.

If a client makes too many requests within a short period of time, the rate limiter will respond with a 429 Too Many Requests status code. This effectively prevents brute force attacks by limiting the number of login attempts that can be made within a certain period of time.

Please note that this is just one part of a comprehensive strategy to protect against brute force attacks. Other measures such as using strong and complex passwords, implementing account lockout mechanisms, using CAPTCHA or other challenge-response mechanisms, implementing two-factor authentication, monitoring and analyzing login logs, educating users about password security, and regularly updating and patching the application should also be considered.

References