Unauthorized access to files - S3 Bucket - Go

Unauthorized access to files - S3 Bucket - Go

Need

Secure access control for S3 buckets

Context

  • Usage of Go 1.15 for building efficient and scalable applications
  • Usage of AWS SDK for Go for interacting with AWS services
  • Usage of AWS SDK Go's session package for managing AWS sessions
  • Usage of AWS SDK for Go to interact with Amazon S3 service
  • Usage of gin-gonic/gin for building web applications and APIs in Go
  • Usage of net/http for creating HTTP servers in a Node.js application

Description

Non compliant code

        package main

import (
    "github.com/aws/aws-sdk-go/aws"
    "github.com/aws/aws-sdk-go/aws/session"
    "github.com/aws/aws-sdk-go/service/s3"
    "github.com/gin-gonic/gin"
    "net/http"
)

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

    sess, _ := session.NewSession(&aws.Config{
        Region: aws.String("us-west-2")},
    )

    svc := s3.New(sess)

    r.GET("/getfile", func(c *gin.Context) {
        input := &s3.GetObjectInput{
            Bucket: aws.String("mybucket"),
            Key:    aws.String("mykey"),
        }

        result, _ := svc.GetObject(input)

        c.Data(http.StatusOK, "application/octet-stream", result)
    })

    r.Run()
}
        
        

This Go code is a simple backend application that uses the Gin framework to handle HTTP requests. A route is set up to handle GET requests to "/getfile". When this route is hit, the application fetches a file from an S3 bucket and sends it as a response.

The vulnerability lies in the fact that there is no authentication or authorization mechanism in place to verify if the user making the request has the right to access the requested file. The S3 bucket's name and key are hardcoded into the application, and the bucket is set to public, meaning anyone who knows the bucket's name and key can access its content.

An attacker could potentially use this vulnerability to download, modify, or delete information stored in the S3 bucket. This is a serious security issue as it could lead to data leakage, unauthorized data modification, and even data loss.

To fix this vulnerability, you should implement an authentication and authorization mechanism to ensure that only authorized users can access the S3 bucket's content. Additionally, you should configure the S3 bucket to be private to prevent unauthorized access.

Steps

  • Ensure that the S3 bucket is not publicly accessible.
  • Implement authentication and authorization mechanisms to control access to the S3 bucket.
  • Use AWS Identity and Access Management (IAM) roles to grant least privilege access to the application.
  • Configure the AWS SDK to use the appropriate credentials for accessing the S3 bucket.
  • Implement proper error handling to handle any authentication or authorization failures.
  • Regularly review and audit the access controls and permissions for the S3 bucket.

Compliant code

        package main

import (
    "github.com/aws/aws-sdk-go/aws"
    "github.com/aws/aws-sdk-go/aws/credentials"
    "github.com/aws/aws-sdk-go/aws/session"
    "github.com/aws/aws-sdk-go/service/s3"
    "github.com/gin-gonic/gin"
    "net/http"
)

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

    sess, _ := session.NewSession(&aws.Config{
        Region: aws.String("us-west-2"),
        Credentials: credentials.NewSharedCredentials("", "myProfile")},
    )

    svc := s3.New(sess)

    r.GET("/getfile", func(c *gin.Context) {
        input := &s3.GetObjectInput{
            Bucket: aws.String("mybucket"),
            Key:    aws.String("mykey"),
        }

        result, err := svc.GetObject(input)
        if err != nil {
            c.JSON(http.StatusInternalServerError, gin.H{"error": "Error retrieving the file"})
            return
        }

        c.Data(http.StatusOK, "application/octet-stream", result)
    })

    r.Run()
}
        
        

The updated code now includes the use of AWS Identity and Access Management (IAM) roles to control access to the S3 bucket. This is done by using the credentials.NewSharedCredentials function to specify the AWS profile that has the necessary permissions to access the S3 bucket.

In addition, error handling has been added to handle any errors that may occur when retrieving the file from the S3 bucket. If an error occurs, a JSON response with a status code of 500 (Internal Server Error) is returned, along with a message indicating that there was an error retrieving the file.

This code ensures that the S3 bucket is not publicly accessible and that only authorized users with the correct IAM roles can access the files in the bucket. It also ensures that any errors that occur are properly handled and communicated to the user.

References