Skip to main content

Inadequate file size control

Need

Implementation of file size restrictions and validation

Context

  • Usage of Go 1.16 for developing scalable and efficient applications
  • Usage of gin-gonic/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.POST("/upload", func(c *gin.Context) {
file, _ := c.FormFile("file")
c.SaveUploadedFile(file, "path/to/save/"+file.Filename)
c.String(http.StatusOK, "File uploaded successfully")
})
r.Run()
}

The above code is a simple file upload server using the Gin framework in Go. When a POST request is made to the "/upload" endpoint, the server accepts the file and saves it to the specified path.

The vulnerability lies in the fact that there is no check on the size of the uploaded file. This could potentially lead to various issues such as:

  • Denial of Service (DoS): An attacker could upload a very large file that could fill up the server's storage, causing the server to stop functioning properly.
  • Server Performance Issues: Processing and storing large files can consume a lot of server resources (CPU, Memory, Disk I/O). If multiple large files are uploaded simultaneously, it could significantly degrade the server's performance.
  • Long Processing Times: If the application processes uploaded files (e.g., for virus scanning, data parsing, etc.), larger files will take longer to process, potentially leading to long request handling times and a poor user experience.

To mitigate this vulnerability, it is recommended to add a check for the file size before processing the uploaded file.

Steps

  • Implement a maximum file size limit for file uploads.
  • Validate the file size before saving it to the server.
  • Return an appropriate error response if the file size exceeds the limit.

Compliant code

package main

import (
"github.com/gin-gonic/gin"
"net/http"
"errors"
)

const MAX_UPLOAD_SIZE = 10 * 1024 * 1024 // 10 MB

func main() {
r := gin.Default()
r.POST("/upload", func(c *gin.Context) {
file, _ := c.FormFile("file")
if file.Size > MAX_UPLOAD_SIZE {
c.JSON(http.StatusBadRequest, gin.H{"error": "File size exceeds the limit"})
return
}
err := c.SaveUploadedFile(file, "path/to/save/"+file.Filename)
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": "Unable to save file"})
return
}
c.String(http.StatusOK, "File uploaded successfully")
})
r.Run()
}

The updated code now includes a constant MAX_UPLOAD_SIZE which is set to 10MB. This constant is used to limit the size of the files that can be uploaded to the server.

In the POST route handler for "/upload", the size of the uploaded file is checked against MAX_UPLOAD_SIZE. If the file size exceeds the limit, the server responds with a 400 Bad Request status and an error message "File size exceeds the limit".

If the file size is within the limit, the server attempts to save the file. If there is an error while saving the file, the server responds with a 500 Internal Server Error status and an error message "Unable to save file".

If the file is saved successfully, the server responds with a 200 OK status and a success message "File uploaded successfully".

References