Prevention of unauthorized access and manipulation of restricted fields
package main
import (
"github.com/gin-gonic/gin"
"net/http"
)
type Employee struct {
DNI string `json:"dni"`
Name string `json:"name"`
Email string `json:"email"`
BirthDate string `json:"birthdate"`
Address string `json:"address"`
PhoneNumber string `json:"phonenumber"`
}
var Employees = make(map[string]Employee)
func RegisterEmployee(c *gin.Context) {
var newEmployee Employee
if err := c.ShouldBindJSON(&newEmployee); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
Employees[newEmployee.DNI] = newEmployee
c.JSON(http.StatusOK, gin.H{"data": newEmployee})
}
func main() {
r := gin.Default()
r.POST("/register", RegisterEmployee)
r.Run()
}
The above code is a simple HTTP server using the Gin framework in Go. It exposes a single endpoint
/register
that accepts a POST request with a JSON body representing an employee. The
RegisterEmployee
function is responsible for handling these requests.
The
Employee
struct is used to parse the incoming JSON body. It contains fields for various pieces of employee data, including DNI, name, email, birthdate, address, and phone number.
The
RegisterEmployee
function uses the
ShouldBindJSON
method provided by Gin to parse the incoming request body into an
Employee
struct. If the parsing is successful, the function then stores the new employee data in the
Employees
map, using the DNI as the key. If the DNI already exists in the map, the existing data will be overwritten with the new data.
This code is vulnerable because it allows any user to update the data of any employee by simply sending a POST request with the target employee's DNI. An attacker could potentially use this to change the information of employees from other companies, as described in the vulnerability context.
package main
import (
"github.com/gin-gonic/gin"
"net/http"
)
type Employee struct {
DNI string `json:"dni"`
Name string `json:"name"`
Email string `json:"email"`
BirthDate string `json:"birthdate"`
Address string `json:"address"`
PhoneNumber string `json:"phonenumber"`
}
var Employees = make(map[string]Employee)
func RegisterEmployee(c *gin.Context) {
var newEmployee Employee
if err := c.ShouldBindJSON(&newEmployee); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
// Check if the user is authenticated and authorized to make changes
user, _ := c.Get("user")
if user == nil || user.(string) != newEmployee.DNI {
c.JSON(http.StatusUnauthorized, gin.H{"error": "You are not authorized to make changes"})
return
}
Employees[newEmployee.DNI] = newEmployee
c.JSON(http.StatusOK, gin.H{"data": newEmployee})
}
func main() {
r := gin.Default()
// Implement middleware for authentication
r.Use(AuthMiddleware())
r.POST("/register", RegisterEmployee)
r.Run()
}
func AuthMiddleware() gin.HandlerFunc {
return func(c *gin.Context) {
// Implement your authentication logic here
// For example, check the Authorization header
token := c.GetHeader("Authorization")
if token == "" {
c.JSON(http.StatusUnauthorized, gin.H{"error": "Unauthorized"})
c.Abort()
return
}
// Validate the token and get the user's DNI
dni, err := validateToken(token)
if err != nil {
c.JSON(http.StatusUnauthorized, gin.H{"error": "Unauthorized"})
c.Abort()
return
}
// Set the user's DNI in the context
c.Set("user", dni)
c.Next()
}
}
func validateToken(token string) (string, error) {
// Implement your token validation logic here
// Return the user's DNI if the token is valid
return "", nil
}
The updated code includes an authentication middleware that checks if the user is authenticated before processing the request. This middleware is added to the Gin router with the
Use
function, so it will be executed for every request.
In the
RegisterEmployee
function, we now check if the user is authorized to make changes. We get the user's DNI from the context, which was set in the authentication middleware, and compare it with the DNI of the new employee. If they don't match, we return an unauthorized error.
The
AuthMiddleware
function is a Gin middleware that checks the Authorization header of the request. If the header is missing or the token is invalid, it returns an unauthorized error and aborts the request. If the token is valid, it sets the user's DNI in the context and continues with the next handler.
The
validateToken
function is a placeholder for your token validation logic. It should validate the token and return the user's DNI if the token is valid. If the token is invalid, it should return an error.
This way, we ensure that only authenticated and authorized users can register employees, and that they can only register employees with their own DNI. This prevents unauthorized users from manipulating the data of other employees.