Out-of-bounds read
Need
Prevention of out-of-bounds read vulnerabilities
Context
- Usage of Go 1.16 for developing high-performance and scalable applications
- Usage of Gin framework for building web applications in Go
Description
Non compliant code
package main
import (
"fmt"
"github.com/gin-gonic/gin"
)
func main() {
r := gin.Default()
r.GET("/read", func(c *gin.Context) {
data := []int{1, 2, 3, 4, 5}
index := c.Query("index")
indexVal, _ := strconv.Atoi(index)
fmt.Println(data[indexVal])
})
r.Run() // run on 0.0.0.0:8080
}
In the above code, we have a simple Gin based HTTP server that has a single GET endpoint "/read". This endpoint reads an index from the query parameters and uses it to access an element in the data
array.
The vulnerability lies in the fact that there is no boundary checking for the index value. This means, if a user provides an index that is outside the bounds of the data
array, the application will attempt to read memory that it shouldn't, leading to an out-of-bounds read vulnerability.
For instance, if a user sends a GET request to "/read?index=10", the application will attempt to access data[10]
, which is outside the bounds of the data
array (which only has indices 0-4). This will result in an out-of-bounds read, which can lead to undefined behavior and potential security risks.
Steps
- Validate the input to ensure it is within the bounds of the data array.
- Check if the index value is a valid integer.
- Handle any potential errors when converting the index value to an integer.
- Implement proper error handling to handle out-of-bounds read scenarios.
- Return an appropriate response to the client if the index is out of bounds.
Compliant code
package main
import (
"fmt"
"github.com/gin-gonic/gin"
"net/http"
"strconv"
)
func main() {
r := gin.Default()
r.GET("/read", func(c *gin.Context) {
data := []int{1, 2, 3, 4, 5}
index := c.Query("index")
indexVal, err := strconv.Atoi(index)
if err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid index value"})
return
}
if indexVal < 0 || indexVal >= len(data) {
c.JSON(http.StatusBadRequest, gin.H{"error": "Index out of bounds"})
return
}
fmt.Println(data[indexVal])
})
r.Run() // run on 0.0.0.0:8080
}
The updated code includes several checks to prevent out-of-bounds read vulnerabilities.
-
Input Validation: The code checks if the index value provided in the request is a valid integer. If the
strconv.Atoi
function returns an error, it means that the index value is not a valid integer. In this case, the code returns a400 Bad Request
response with an error message "Invalid index value". -
Bounds Checking: The code checks if the index value is within the bounds of the
data
array. If the index value is less than 0 or greater than or equal to the length of thedata
array, it means that the index is out of bounds. In this case, the code returns a400 Bad Request
response with an error message "Index out of bounds".
These checks ensure that the system only reads data within the intended buffer, preventing out-of-bounds read vulnerabilities.