Authentication mechanism absence or evasion - Admin Console - Go

Authentication mechanism absence or evasion - Admin Console - Go

Need

Implementation of a robust authentication mechanism for the Admin Console

Context

  • Usage of Go 1.16 for developing scalable and efficient applications
  • Usage of Gin framework for building web applications in Go

Description

Non compliant code

        package main

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

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

	r.GET("/admin", func(c *gin.Context) {
		c.JSON(200, gin.H{
			"message": "Welcome to the admin console!",
		})
	})

	r.POST("/admin/edit", func(c *gin.Context) {
		// Code to edit values
		c.JSON(200, gin.H{
			"message": "Values edited successfully",
		})
	})

	r.Run() // listen and serve on 0.0.0.0:8080 (for windows "localhost:8080")
}
        
        

The above code represents a basic server using the Gin framework in Go. It has two routes: /admin and /admin/edit.

The /admin route is a GET route that allows anyone to view the admin console just by accessing the URL. No authentication is required, which means any user, even those who are not logged in, can access this route.

The /admin/edit route is a POST route that allows anyone to edit values. Again, no authentication is required to access this route. This means that any user, including those who are not logged in, can make changes to the values.

This is a major security vulnerability as it allows unauthorized users to view and change sensitive information.

Steps

  • Implement an authentication mechanism to restrict access to the admin console.
  • Require users to authenticate before accessing any admin functionality.
  • Use a secure authentication method, such as username/password or token-based authentication.
  • Ensure that only authorized users have access to the admin console.
  • Implement authorization checks to restrict certain actions to specific roles or permissions.
  • Regularly review and update the authentication and authorization mechanisms to address any potential vulnerabilities.

Compliant code

        package main

import (
	"github.com/gin-gonic/gin"
	"github.com/gin-contrib/sessions"
	"github.com/gin-contrib/sessions/cookie"
)

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

	store := cookie.NewStore([]byte("secret"))
	r.Use(sessions.Sessions("mysession", store))

	r.GET("/login", func(c *gin.Context) {
		c.HTML(200, "login.html", nil)
	})

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

		// Validate the username and password from your database
		if isValid := validateCredentials(username, password); isValid {
			session := sessions.Default(c)
			session.Set("user", username)
			session.Save()
			c.JSON(200, gin.H{"message": "You are logged in"})
		} else {
			c.JSON(401, gin.H{"message": "Authentication failed"})
		}
	})

	authorized := r.Group("/", AuthRequired())
	{
		authorized.GET("/admin", func(c *gin.Context) {
			c.JSON(200, gin.H{
				"message": "Welcome to the admin console!",
			})
		})

		authorized.POST("/admin/edit", func(c *gin.Context) {
			// Code to edit values
			c.JSON(200, gin.H{
				"message": "Values edited successfully",
			})
		})
	}

	r.Run() // listen and serve on 0.0.0.0:8080 (for windows "localhost:8080")
}

func AuthRequired() gin.HandlerFunc {
	return func(c *gin.Context) {
		session := sessions.Default(c)
		user := session.Get("user")
		if user == nil {
			c.JSON(401, gin.H{"error": "Unauthorized"})
			c.Abort()
			return
		}
		c.Next()
	}
}

func validateCredentials(username, password string) bool {
	// Replace with your own logic
	return username == "admin" && password == "password"
}
        
        

The updated code now includes an authentication mechanism using sessions. The github.com/gin-contrib/sessions package is used to manage sessions in the application.

A new session store is created using a secret key and the Sessions middleware is added to the Gin engine.

Two new routes, /login (GET) and /login (POST), are added to handle user login. The POST route checks the provided username and password against a validateCredentials function (replace this with your own logic to validate credentials against a database or other source).

The /admin and /admin/edit routes are now part of an authorized group, which uses the AuthRequired middleware. This middleware checks if a user is stored in the session, and if not, it aborts the request and returns a 401 Unauthorized error.

This way, only authenticated users can access the admin console and edit values. Unauthorized users will be blocked and receive an error message.

References