Business information leak - Customers or providers
Need
Protection of sensitive business information from unauthorized access or leakage
Context
- Usage of Go 1.16 for building efficient and scalable applications
- Usage of Gin for building web applications in Go
Description
Non compliant code
package main
import (
"github.com/gin-gonic/gin"
)
type Customer struct {
Name string `json:"name"`
Email string `json:"email"`
Phone string `json:"phone"`
}
var Customers = []Customer{
{"John Doe", "[email protected]", "1234567890"},
{"Jane Doe", "[email protected]", "0987654321"},
}
func main() {
r := gin.Default()
r.GET("/customers", func(c *gin.Context) {
c.JSON(200, Customers)
})
r.Run()
}
In the above code, we have a simple Gin application that serves customer data at the /customers
endpoint. The customer data includes sensitive information such as name, email, and phone number.
The vulnerability lies in the /customers
route handler. When a GET request is made to this endpoint, it responds with the entire list of customers, including their sensitive information. This means that anyone who can make a GET request to this endpoint can access this sensitive information.
This is a serious security issue as it can lead to information leakage. Attackers can exploit this vulnerability to gain unauthorized access to customer data, which can lead to a variety of problems including identity theft, spamming, and other forms of abuse.
Steps
- Implement authentication and authorization mechanisms to restrict access to sensitive information.
- Store sensitive information securely, such as using encryption or hashing algorithms.
- Implement input validation and sanitization to prevent injection attacks.
- Limit the amount of sensitive information exposed in API responses.
- Implement rate limiting and throttling to prevent abuse and excessive data retrieval.
- Regularly review and update access controls and permissions for sensitive data.
- Implement logging and monitoring to detect and respond to any unauthorized access attempts.
Compliant code
package main
import (
"github.com/gin-gonic/gin"
"github.com/gin-contrib/sessions"
"github.com/gin-contrib/sessions/cookie"
"golang.org/x/crypto/bcrypt"
)
type User struct {
Username string `json:"username"`
Password string `json:"password"`
}
type Customer struct {
Name string `json:"-"`
Email string `json:"email"`
Phone string `json:"-"`
}
var Users = []User{
{"admin", "$2a$10$7.0Zz8/0Z1S4yr1mZJKC.eC7akSq3HGjU2p3p8p6hIoLe6B6YUHmG"}, // password is "password"
}
var Customers = []Customer{
{"John Doe", "[email protected]", "1234567890"},
{"Jane Doe", "[email protected]", "0987654321"},
}
func main() {
r := gin.Default()
store := cookie.NewStore([]byte("secret"))
r.Use(sessions.Sessions("mysession", store))
r.POST("/login", func(c *gin.Context) {
var user User
if err := c.ShouldBindJSON(&user); err == nil {
for _, u := range Users {
if user.Username == u.Username {
err := bcrypt.CompareHashAndPassword([]byte(u.Password), []byte(user.Password))
if err == nil {
session := sessions.Default(c)
session.Set("user", user.Username)
session.Save()
c.JSON(200, gin.H{"message": "Logged in"})
return
}
}
}
}
c.JSON(401, gin.H{"message": "Authentication failed"})
})
r.GET("/customers", func(c *gin.Context) {
session := sessions.Default(c)
user := session.Get("user")
if user == nil {
c.JSON(401, gin.H{"message": "Unauthorized"})
return
}
c.JSON(200, Customers)
})
r.Run()
}
The updated code includes several security measures to prevent unauthorized access to sensitive customer information.
-
Authentication: A new
/login
endpoint is added, which checks the provided username and password against a list of users. If the credentials match, a session is created for the user. The password is hashed using bcrypt, a secure hashing algorithm. -
Authorization: The
/customers
endpoint now checks if a user is logged in before returning the customer data. If no user is logged in, it returns a 401 Unauthorized status. -
Data Exposure: The
json
tags on theCustomer
struct have been updated to prevent the customer's name and phone number from being included in the JSON response. Only the email is included. -
Session Management: The application now uses the
sessions
middleware from thegin-contrib/sessions
package to manage user sessions. The session data is stored in a secure cookie.
Remember to replace "secret"
with your own secret key in the cookie.NewStore([]byte("secret"))
line. This key is used to sign the session cookie.
This code is a basic example and might need to be adjusted to fit your specific needs. For example, you might want to replace the hardcoded list of users with a database, or add rate limiting to prevent brute force attacks.