Skip to main content

Lack of protection against deletion

Need

Implementation of safeguards to prevent accidental deletion of critical objects

Context

  • Usage of Go 1.16 for building high-performance and scalable applications
  • Usage of gin-gonic/gin for building web applications in Go

Description

Non compliant code

package main

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

type Object struct {
ID string `json:"id"`
}

var objects = make(map[string]Object)

func deleteObject(c *gin.Context) {
id := c.Param("id")
delete(objects, id)
c.JSON(200, gin.H{"status": "object deleted"})
}

func main() {
r := gin.Default()
r.DELETE("/object/:id", deleteObject)
r.Run()
}

This is a simple Gin application written in Go. It has a single endpoint /object/:id that accepts DELETE requests. The deleteObject function retrieves the id from the request parameters and deletes the corresponding object from the objects map.

The vulnerability lies in the deleteObject function. It does not perform any checks before deleting an object. This means any object can be deleted, even if it's critical. If an attacker discovers the ID of a critical object, they can send a DELETE request to remove it. This could lead to loss of important data.

Additionally, there is no mechanism to prevent accidental deletion. A simple mistake could lead to the removal of critical objects. This also makes it hard to recover deleted objects since there is no backup or versioning system in place.

Steps

  • Implement authentication and authorization mechanisms to ensure that only authorized users can delete objects.
  • Add validation checks to ensure that the object being deleted is not critical or important.
  • Implement a confirmation mechanism to prevent accidental deletion of objects.
  • Consider implementing a soft delete mechanism instead of directly deleting objects, allowing for recovery if needed.
  • Regularly backup the data to prevent permanent loss in case of accidental deletion.

Compliant code

package main

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

type Object struct {
ID string `json:"id"`
IsCritical bool `json:"isCritical"`
}

var objects = make(map[string]Object)

func deleteObject(c *gin.Context) {
id := c.Param("id")
object, exists := objects[id]
if !exists {
c.JSON(404, gin.H{"status": "object not found"})
return
}
if object.IsCritical {
c.JSON(403, gin.H{"status": "cannot delete critical object"})
return
}
delete(objects, id)
c.JSON(200, gin.H{"status": "object deleted"})
}

func main() {
r := gin.Default()
r.DELETE("/object/:id", deleteObject)
r.Run()
}

The updated code includes several changes to address the vulnerability:

  1. Object Structure: The Object struct now includes a IsCritical boolean field. This field is used to mark objects that are critical and should not be deleted.

  2. Delete Function: The deleteObject function now includes checks to ensure that the object exists and is not marked as critical before deletion. If the object does not exist, a 404 status code is returned. If the object is marked as critical, a 403 status code is returned.

This code does not include authentication or authorization mechanisms, as these would depend on the specifics of your application. However, you should ensure that only authorized users can access the deleteObject function.

Additionally, this code does not include a soft delete mechanism or regular backups. These are important considerations for preventing data loss, but they would also depend on the specifics of your application and are not included in this example.

References