Skip to main content

Guessed weak credentials

Need

Enhancement of credential security

Context

  • Usage of Go 1.16 for building high-performance and efficient applications
  • Usage of gin-gonic/gin for building web applications and APIs in Go
  • Usage of net/http for creating a server and handling HTTP requests 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) {
username := c.PostForm("username")
password := c.PostForm("password")

if username == "admin" && password == "1234" {
c.JSON(http.StatusOK, gin.H{"status": "you are logged in"})
} else {
c.JSON(http.StatusUnauthorized, gin.H{"status": "unauthorized"})
}
})
r.Run(":8080")
}

In the above code, the /login endpoint is vulnerable to brute force attacks due to the use of weak and easily guessable credentials.

Here, the username and password are hardcoded as admin and 1234 respectively. These are very common and weak credentials that can be easily guessed by an attacker.

The code does not implement any sort of password complexity requirements or account lockout mechanism after a certain number of failed attempts. This means that an attacker could potentially use a brute force attack to guess the credentials and gain unauthorized access to the system.

Moreover, the code does not use any form of encryption when storing or comparing the credentials, which could lead to further vulnerabilities if the credentials were to be intercepted or the codebase compromised.

Steps

  • Implement a strong password policy that enforces complex passwords.
  • Use a secure password hashing algorithm to store passwords.
  • Implement account lockout mechanisms to prevent brute force attacks.
  • Use a secure authentication mechanism such as multi-factor authentication.
  • Regularly update and patch the application and its dependencies to address any security vulnerabilities.
  • Implement rate limiting to prevent excessive login attempts.
  • Educate users about the importance of using strong and unique passwords.

Compliant code

package main

import (
"github.com/gin-gonic/gin"
"golang.org/x/crypto/bcrypt"
"net/http"
"time"
)

var loginAttempts = make(map[string]int)
var blockUntil = make(map[string]time.Time)

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

// Check if user is blocked
if blockUntil[username].After(time.Now()) {
c.JSON(http.StatusTooManyRequests, gin.H{"status": "Too many failed login attempts. Try again later."})
return
}

// Hashed password for "admin". In a real application, this would be retrieved from a database.
hashedPassword, _ := bcrypt.GenerateFromPassword([]byte("ComplexPassword!23"), bcrypt.DefaultCost)

// Compare the stored hashed password, with the hashed version of the password that was received
if username == "admin" && bcrypt.CompareHashAndPassword(hashedPassword, []byte(password)) == nil {
// Reset login attempts
loginAttempts[username] = 0
c.JSON(http.StatusOK, gin.H{"status": "you are logged in"})
} else {
// Increment login attempts
loginAttempts[username]++

// Block user after 3 failed attempts
if loginAttempts[username] > 3 {
blockUntil[username] = time.Now().Add(5 * time.Minute)
}

c.JSON(http.StatusUnauthorized, gin.H{"status": "unauthorized"})
}
})
r.Run(":8080")
}

The updated code includes several security enhancements to mitigate the risk of brute force attacks and weak passwords.

  1. Strong Password Policy: The password for the "admin" user has been changed to a complex password. In a real application, you would enforce a strong password policy and ensure that users choose complex passwords.

  2. Password Hashing: Passwords are now stored as hashed values using the bcrypt algorithm. When a user attempts to log in, the submitted password is hashed and compared to the stored hashed password. This means that even if an attacker gains access to the system, they will not be able to see the actual passwords.

  3. Account Lockout Mechanism: The system now keeps track of failed login attempts. If a user fails to log in more than 3 times, their account is blocked for 5 minutes. This helps to prevent brute force attacks by slowing down repeated login attempts.

  4. Rate Limiting: The system also implements rate limiting. If a user makes too many requests within a certain timeframe, they are temporarily blocked.

In addition to these code changes, it's also important to regularly update and patch the application and its dependencies, use secure authentication mechanisms such as multi-factor authentication, and educate users about the importance of using strong and unique passwords.

References