Administrative credentials stored in cache memory - Go

Administrative credentials stored in cache memory - Go

Need

Secure storage of administrative credentials

Context

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

var adminCreds = "admin:password"

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

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

In this code, we have a simple login endpoint in a Go application using the Gin framework. The adminCreds variable contains the administrative credentials in the form of "username:password". The application checks if the provided username and password match the stored adminCreds to authenticate the user.

The vulnerability lies in the fact that the administrative credentials are stored in plain text in the memory. This means that if an attacker gains access to the memory of the system, they can retrieve the administrative credentials. This is a severe security risk as it can lead to unauthorized access and potential misuse of the system.

Additionally, the credentials are also static and hard-coded, which is another bad practice. The credentials should be securely stored in a place like a secure vault or environment variables and should be encrypted.

Steps

  • Do not store sensitive information, such as administrative credentials, in code or variables.
  • Use a secure and encrypted storage mechanism, such as a secure database or a key management system, to store administrative credentials.
  • Implement proper authentication and authorization mechanisms to validate user credentials.
  • Avoid logging or printing sensitive information, including administrative credentials, in logs or error messages.
  • Regularly review and update the access control policies and permissions for administrative accounts.
  • Implement secure session management to prevent unauthorized access to administrative accounts.
  • Regularly monitor and analyze system logs for any suspicious activities or unauthorized access attempts.
  • Educate developers and administrators about secure coding practices and the importance of protecting sensitive information.

Compliant code

        package main

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

var hashedAdminPassword, _ = bcrypt.GenerateFromPassword([]byte("password"), bcrypt.DefaultCost)

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

		if username == "admin" && bcrypt.CompareHashAndPassword(hashedAdminPassword, []byte(password)) == nil {
			c.JSON(http.StatusOK, gin.H{"status": "you are logged in"})
		} else {
			c.JSON(http.StatusUnauthorized, gin.H{"status": "unauthorized"})
		}
	})
	r.Run()
}
        
        

The original code had a vulnerability where it stored administrative credentials in a variable in plain text. This is a security risk as it exposes sensitive information that could be exploited by malicious actors.

The fixed code addresses this vulnerability by using the bcrypt library to hash the administrative password. The hashed password is then stored in a variable instead of the plain text password. When a user attempts to log in, the entered password is hashed and compared to the stored hashed password. This way, even if an attacker gains access to the code, they would only see the hashed password, which is useless without the original password.

In addition, the fixed code checks if the username is "admin" and the hashed password matches the stored hashed password. If both checks pass, the user is logged in. If not, an "unauthorized" message is returned.

This fix improves the security of the application by protecting sensitive information and implementing a secure authentication mechanism. However, it is still recommended to store sensitive information such as passwords in a secure and encrypted storage mechanism, such as a secure database or a key management system.

References