Anonymous connection - Go

Anonymous connection - Go

Need

Restriction of anonymous access to the server

Context

  • Usage of Go 1.16 for building high-performance and scalable applications
  • Usage of Gin for building web applications in Go
  • Usage of net/http for creating HTTP servers 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.GET("/protected", func(c *gin.Context) {
		username, password, _ := c.Request.BasicAuth()

		if username == "anonymous" && password == "guest" {
			c.JSON(http.StatusOK, gin.H{
				"message": "You have accessed protected resources!",
			})
		} else {
			c.JSON(http.StatusUnauthorized, gin.H{
				"message": "Unauthorized",
			})
		}
	})

	r.Run() // listen and serve on 0.0.0.0:8080
}
        
        

The above code is a simple HTTP server using the Gin framework in Go. It has a single route, /protected, which is intended to be a protected resource. However, due to the insecure configuration, it is possible to access this protected resource by using the username anonymous and password guest.

The vulnerability lies in the following lines of code:

                username, password, _ := c.Request.BasicAuth()

if username == "anonymous" && password == "guest" { c.JSON(http.StatusOK, gin.H{ "message": "You have accessed protected resources!", }) } else { c.JSON(http.StatusUnauthorized, gin.H{ "message": "Unauthorized", }) }


Here, the server is checking if the Basic Authentication credentials provided in the request match the username anonymous and password guest. If they do, the server responds with a 200 status code and a message indicating that the protected resource has been accessed. If they do not, the server responds with a 401 status code and a message indicating that the request is unauthorized.

This configuration allows any user who knows these credentials to access the protected resource, creating a security vulnerability.

Steps

  • Remove the hardcoded 'anonymous' username and 'guest' password from the code.
  • Implement a proper authentication mechanism, such as user registration and login.
  • Use secure protocols, such as HTTPS, to protect sensitive data during transmission.
  • Implement access control mechanisms to restrict access to protected resources based on user roles and permissions.
  • Regularly update and patch the server and its dependencies to address any security vulnerabilities.

Compliant code

        package main

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

var users = map[string]string{
	"user1": "$2a$10$N9qo8uLOickgx2ZMRZoHK.ApicMYtB2aF7fIxuzM0hm.9Bc8EvN32", //password: password1
	"user2": "$2a$10$2bDfgB4y0hRPe7Ei67zqeOzSPGsQUOh3y2wrXCw5m8xZiBQWgQqka", //password: password2
}

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

	r.GET("/protected", func(c *gin.Context) {
		username, password, _ := c.Request.BasicAuth()

		if hashedPassword, ok := users[username]; ok {
			err := bcrypt.CompareHashAndPassword([]byte(hashedPassword), []byte(password))
			if err == nil {
				c.JSON(http.StatusOK, gin.H{
					"message": "You have accessed protected resources!",
				})
				return
			}
		}

		c.JSON(http.StatusUnauthorized, gin.H{
			"message": "Unauthorized",
		})
	})

	r.Run() // listen and serve on 0.0.0.0:8080
}
        
        

The updated code now uses a map to store usernames and their corresponding hashed passwords. The bcrypt library is used to hash and compare passwords, which is a more secure way of handling user passwords.

When a GET request is made to the "/protected" endpoint, the server retrieves the username and password from the request's BasicAuth header. It then checks if the username exists in the users map. If it does, the server compares the hashed password stored in the map with the password from the request using bcrypt's CompareHashAndPassword function. If the passwords match, the server responds with a success message. If they don't match or if the username doesn't exist in the map, the server responds with an "Unauthorized" message.

This code is more secure because it doesn't allow anonymous connections. Users must provide a valid username and password to access protected resources. The use of bcrypt to hash and compare passwords also adds an extra layer of security.

Remember to use HTTPS to protect sensitive data during transmission and implement access control mechanisms to restrict access to protected resources based on user roles and permissions. Regularly update and patch the server and its dependencies to address any security vulnerabilities.

References