From 5a9f20e8717bf7818e694d7ea376795a6cd9a7a2 Mon Sep 17 00:00:00 2001 From: ZeroPath Date: Mon, 3 Feb 2025 02:59:48 +0000 Subject: [PATCH 1/2] fix: Address IDOR vulnerability in GetTicket function with authorization checks --- .../a1/ecommerce-api/app/handlers/handlers.go | 20 +++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/owasp-top10-2021-apps/a1/ecommerce-api/app/handlers/handlers.go b/owasp-top10-2021-apps/a1/ecommerce-api/app/handlers/handlers.go index ea71f28d2..b648b1fa3 100644 --- a/owasp-top10-2021-apps/a1/ecommerce-api/app/handlers/handlers.go +++ b/owasp-top10-2021-apps/a1/ecommerce-api/app/handlers/handlers.go @@ -13,13 +13,25 @@ func HealthCheck(c echo.Context) error { return c.String(http.StatusOK, "WORKING\n") } -// GetTicket returns the userID ticket. +// GetTicket returns the authenticated user's ticket. func GetTicket(c echo.Context) error { - id := c.Param("id") - userDataQuery := map[string]interface{}{"userID": id} + // Get authenticated user's ID from the session/token + authenticatedUserID := c.Get("user") + if authenticatedUserID == nil { + return c.JSON(http.StatusUnauthorized, map[string]string{"result": "error", "details": "Authentication required"}) + } + + // Get requested user ID from path parameter + requestedID := c.Param("id") + + // Verify user is accessing their own ticket + if authenticatedUserID.(string) != requestedID { + return c.JSON(http.StatusForbidden, map[string]string{"result": "error", "details": "Access denied"}) + } + + userDataQuery := map[string]interface{}{"userID": requestedID} userDataResult, err := db.GetUserData(userDataQuery) if err != nil { - // could not find this user in MongoDB (or MongoDB err connection) return c.JSON(http.StatusBadRequest, map[string]string{"result": "error", "details": "Error finding this UserID."}) } From a1189002ac6944c89d359df0d697958bcd740e0d Mon Sep 17 00:00:00 2001 From: ZeroPath Date: Mon, 3 Feb 2025 03:30:47 +0000 Subject: [PATCH 2/2] feat: Create reusable authentication helper for user access validation --- .../a1/ecommerce-api/app/handlers/auth.go | 26 +++++++++++++++++++ .../a1/ecommerce-api/app/handlers/handlers.go | 12 ++------- 2 files changed, 28 insertions(+), 10 deletions(-) create mode 100644 owasp-top10-2021-apps/a1/ecommerce-api/app/handlers/auth.go diff --git a/owasp-top10-2021-apps/a1/ecommerce-api/app/handlers/auth.go b/owasp-top10-2021-apps/a1/ecommerce-api/app/handlers/auth.go new file mode 100644 index 000000000..6a4ffef11 --- /dev/null +++ b/owasp-top10-2021-apps/a1/ecommerce-api/app/handlers/auth.go @@ -0,0 +1,26 @@ +package handlers + +import ( + "github.com/labstack/echo" + "net/http" +) + +// ValidateUserAccess checks if the authenticated user has access to the requested resource +func ValidateUserAccess(c echo.Context, requestedID string) error { + authenticatedUserID := c.Get("user") + if authenticatedUserID == nil { + return echo.NewHTTPError(http.StatusUnauthorized, map[string]string{ + "result": "error", + "details": "Authentication required", + }) + } + + if authenticatedUserID.(string) != requestedID { + return echo.NewHTTPError(http.StatusForbidden, map[string]string{ + "result": "error", + "details": "Access denied", + }) + } + + return nil +} diff --git a/owasp-top10-2021-apps/a1/ecommerce-api/app/handlers/handlers.go b/owasp-top10-2021-apps/a1/ecommerce-api/app/handlers/handlers.go index b648b1fa3..ead3a8bd5 100644 --- a/owasp-top10-2021-apps/a1/ecommerce-api/app/handlers/handlers.go +++ b/owasp-top10-2021-apps/a1/ecommerce-api/app/handlers/handlers.go @@ -15,18 +15,10 @@ func HealthCheck(c echo.Context) error { // GetTicket returns the authenticated user's ticket. func GetTicket(c echo.Context) error { - // Get authenticated user's ID from the session/token - authenticatedUserID := c.Get("user") - if authenticatedUserID == nil { - return c.JSON(http.StatusUnauthorized, map[string]string{"result": "error", "details": "Authentication required"}) - } - - // Get requested user ID from path parameter requestedID := c.Param("id") - // Verify user is accessing their own ticket - if authenticatedUserID.(string) != requestedID { - return c.JSON(http.StatusForbidden, map[string]string{"result": "error", "details": "Access denied"}) + if err := ValidateUserAccess(c, requestedID); err != nil { + return err } userDataQuery := map[string]interface{}{"userID": requestedID}