From bb6363bdcdad69c26a5e3a035afed3ceebef8655 Mon Sep 17 00:00:00 2001 From: meiryleneavelino Date: Wed, 13 Nov 2024 15:05:10 -0300 Subject: [PATCH 1/9] =?UTF-8?q?Solu=C3=A7=C3=A3o=20Meiry=20Broken=20Acess?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../a1/ecommerce-api/app/handlers/handlers.go | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) 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..83890fc44 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 @@ -14,9 +14,20 @@ func HealthCheck(c echo.Context) error { } // GetTicket returns the userID ticket. +//Precisamos garantir que essa função só seja acessada por usuários autenticados +// O userID corresponde ao UserID do solicitante??? func GetTicket(c echo.Context) error { - id := c.Param("id") + + authuserID := c.Get("userID").string //Id do usuário autenticado + + id := c.Param("id") //extrai o ID do usuário da URL + + if authuserID != id{ + return c.JSON(http.StatusForbidden, map[string]string{"result": "error", "details": "Access denied."}) + } + userDataQuery := map[string]interface{}{"userID": id} + userDataResult, err := db.GetUserData(userDataQuery) if err != nil { // could not find this user in MongoDB (or MongoDB err connection) From 2966f0c5c4042c59f99cbedb04c7fd204f27600f Mon Sep 17 00:00:00 2001 From: meiryleneavelino Date: Wed, 13 Nov 2024 15:34:42 -0300 Subject: [PATCH 2/9] =?UTF-8?q?Solu=C3=A7=C3=A3o=20Meiry=20Broken=20Acess?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- owasp-top10-2021-apps/a1/ecommerce-api/app/handlers/handlers.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 83890fc44..3be2921c8 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 @@ -18,7 +18,7 @@ func HealthCheck(c echo.Context) error { // O userID corresponde ao UserID do solicitante??? func GetTicket(c echo.Context) error { - authuserID := c.Get("userID").string //Id do usuário autenticado + authuserID := c.Get("userID").(string)//Id do usuário autenticado id := c.Param("id") //extrai o ID do usuário da URL From 84d54b090179d3d355a34e4536cee4b347c54496 Mon Sep 17 00:00:00 2001 From: meiryleneavelino Date: Wed, 13 Nov 2024 16:35:44 -0300 Subject: [PATCH 3/9] =?UTF-8?q?Solu=C3=A7=C3=A3o-Broken=20Acess?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../a1/ecommerce-api/app/handlers/handlers.go | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 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 3be2921c8..096002418 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 @@ -18,11 +18,17 @@ func HealthCheck(c echo.Context) error { // O userID corresponde ao UserID do solicitante??? func GetTicket(c echo.Context) error { - authuserID := c.Get("userID").(string)//Id do usuário autenticado + //authuserId := c.Get("userID").(string)//Id do usuário autenticado + + authuserID,ok:= c.Get("userID").(string) + if !ok { + return c.JSON(http.StatusUnauthorized, map[string]string{"result": "error", "details": "User not authenticated"}) + } id := c.Param("id") //extrai o ID do usuário da URL + - if authuserID != id{ + if authuserId != id{ return c.JSON(http.StatusForbidden, map[string]string{"result": "error", "details": "Access denied."}) } From 84e309a57ac3fa4a5c49f7b849d9b9a7a5800bfc Mon Sep 17 00:00:00 2001 From: meiryleneavelino Date: Wed, 13 Nov 2024 17:33:42 -0300 Subject: [PATCH 4/9] =?UTF-8?q?Solu=C3=A7=C3=A3o-Broken=20Acess?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- owasp-top10-2021-apps/a1/ecommerce-api/app/handlers/handlers.go | 1 + 1 file changed, 1 insertion(+) 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 096002418..b2097036c 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 @@ -21,6 +21,7 @@ func GetTicket(c echo.Context) error { //authuserId := c.Get("userID").(string)//Id do usuário autenticado authuserID,ok:= c.Get("userID").(string) + if !ok { return c.JSON(http.StatusUnauthorized, map[string]string{"result": "error", "details": "User not authenticated"}) } From de628540d9998f21d20301f37f1222d2cc1dedfc Mon Sep 17 00:00:00 2001 From: meiryleneavelino Date: Tue, 26 Nov 2024 21:16:54 -0300 Subject: [PATCH 5/9] tentativa --- .../a1/ecommerce-api/app/db/mongo.go | 62 +++++---- .../a1/ecommerce-api/app/handlers/handlers.go | 75 +++++------ .../a1/ecommerce-api/app/server.go | 124 ++++++++++++------ 3 files changed, 156 insertions(+), 105 deletions(-) diff --git a/owasp-top10-2021-apps/a1/ecommerce-api/app/db/mongo.go b/owasp-top10-2021-apps/a1/ecommerce-api/app/db/mongo.go index d60a4e5f4..d5a1d097f 100644 --- a/owasp-top10-2021-apps/a1/ecommerce-api/app/db/mongo.go +++ b/owasp-top10-2021-apps/a1/ecommerce-api/app/db/mongo.go @@ -10,7 +10,8 @@ import ( // Collections names used in MongoDB. var ( - UserCollection = "users" + UserCollection = "users" + TicketsCollection = "tickets" // Adicione a coleção de tickets ) // DB is the struct that represents mongo session. @@ -34,6 +35,7 @@ type Database interface { UpdateAll(query, updateQuery bson.M, collection string) error Upsert(query bson.M, obj interface{}, collection string) (*mgo.ChangeInfo, error) SearchOne(query bson.M, selectors []string, collection string, obj interface{}) error + CheckUserPermission(userID, ticketID string) (bool, error) // Adicionado para refletir a sugestão } var config = &mongoConfig{ @@ -45,8 +47,6 @@ var config = &mongoConfig{ // Connect connects to mongo and returns the session. func Connect() (*DB, error) { - - // fmt.Printf("config:%#v", config) dialInfo := &mgo.DialInfo{ Addrs: []string{config.Address}, Timeout: time.Second * 60, @@ -64,31 +64,36 @@ func Connect() (*DB, error) { return nil, err } - //go autoReconnect(session) - return &DB{Session: session}, nil } -// autoReconnect checks mongo's connection each second and, if an error is found, reconnect to it. -func autoReconnect(session *mgo.Session) { - var err error - for { - err = session.Ping() - if err != nil { - session.Refresh() - err = session.Ping() - if err == nil { - } else { - } +// CheckUserPermission verifies if a user has access to a specific ticket. +func (db *DB) CheckUserPermission(userID, ticketID string) (bool, error) { + session := db.Session.Clone() + defer session.Close() + c := session.DB(config.DatabaseName).C(TicketsCollection) + + query := bson.M{ + "userID": userID, + "ticketID": ticketID, + } + + var result bson.M + err := c.Find(query).One(&result) + if err != nil { + if err == mgo.ErrNotFound { + return false, nil } - time.Sleep(time.Second * 1) + return false, err } + + return true, nil } // Insert inserts a new document. func (db *DB) Insert(obj interface{}, collection string) error { session := db.Session.Clone() - c := session.DB("").C(collection) + c := session.DB(config.DatabaseName).C(collection) defer session.Close() return c.Insert(obj) } @@ -96,26 +101,25 @@ func (db *DB) Insert(obj interface{}, collection string) error { // Update updates a single document. func (db *DB) Update(query, updateQuery interface{}, collection string) error { session := db.Session.Clone() - c := session.DB("").C(collection) + c := session.DB(config.DatabaseName).C(collection) defer session.Close() - err := c.Update(query, updateQuery) - return err + return c.Update(query, updateQuery) } // UpdateAll updates all documents that match the query. -func (db *DB) UpdateAll(query, updateQuery interface{}, collection string) error { +func (db *DB) UpdateAll(query, updateQuery bson.M, collection string) error { session := db.Session.Clone() - c := session.DB("").C(collection) + c := session.DB(config.DatabaseName).C(collection) defer session.Close() _, err := c.UpdateAll(query, updateQuery) return err } -// Search searchs all documents that match the query. If selectors are present, the return will be only the chosen fields. +// Search searches all documents that match the query. If selectors are present, the return will be only the chosen fields. func (db *DB) Search(query bson.M, selectors []string, collection string, obj interface{}) error { session := db.Session.Clone() defer session.Close() - c := session.DB("").C(collection) + c := session.DB(config.DatabaseName).C(collection) var err error if selectors != nil { @@ -133,11 +137,11 @@ func (db *DB) Search(query bson.M, selectors []string, collection string, obj in return err } -// SearchOne searchs for the first element that matchs with the given query. +// SearchOne searches for the first element that matches with the given query. func (db *DB) SearchOne(query bson.M, selectors []string, collection string, obj interface{}) error { session := db.Session.Clone() defer session.Close() - c := session.DB("").C(collection) + c := session.DB(config.DatabaseName).C(collection) var err error if selectors != nil { @@ -155,10 +159,10 @@ func (db *DB) SearchOne(query bson.M, selectors []string, collection string, obj return err } -// Upsert inserts a document or update it if it already exists. +// Upsert inserts a document or updates it if it already exists. func (db *DB) Upsert(query bson.M, obj interface{}, collection string) (*mgo.ChangeInfo, error) { session := db.Session.Clone() - c := session.DB("").C(collection) + c := session.DB(config.DatabaseName).C(collection) defer session.Close() return c.Upsert(query, obj) } 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 b2097036c..97afd8422 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 @@ -14,42 +14,43 @@ func HealthCheck(c echo.Context) error { } // GetTicket returns the userID ticket. -//Precisamos garantir que essa função só seja acessada por usuários autenticados -// O userID corresponde ao UserID do solicitante??? func GetTicket(c echo.Context) error { - - //authuserId := c.Get("userID").(string)//Id do usuário autenticado - - authuserID,ok:= c.Get("userID").(string) - - if !ok { - return c.JSON(http.StatusUnauthorized, map[string]string{"result": "error", "details": "User not authenticated"}) - } - - id := c.Param("id") //extrai o ID do usuário da URL - - - if authuserId != id{ - return c.JSON(http.StatusForbidden, map[string]string{"result": "error", "details": "Access denied."}) - } - - userDataQuery := map[string]interface{}{"userID": id} - - 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."}) - } - - format := c.QueryParam("format") - if format == "json" { - return c.JSON(http.StatusOK, map[string]string{ - "result": "success", - "username": userDataResult.Username, - "ticket": userDataResult.Ticket, - }) - } - - msgTicket := fmt.Sprintf("Hey, %s! This is your ticket: %s\n", userDataResult.Username, userDataResult.Ticket) - return c.String(http.StatusOK, msgTicket) + // Obter o userID do contexto (definido por um middleware de autenticação) + userIDFromContext := c.Get("userID").(string) // Assumindo que o middleware adiciona userID no contexto + + // Obter o userID da URL + id := c.Param("id") + + // Verificar se o userID autenticado corresponde ao userID fornecido + if userIDFromContext != id { + return c.JSON(http.StatusForbidden, map[string]string{ + "result": "error", + "details": "Access denied. You are not authorized to view this ticket.", + }) + } + + // Consultar o banco de dados com base no userID + userDataQuery := map[string]interface{}{"userID": id} + userDataResult, err := db.GetUserData(userDataQuery) + if err != nil { + // Erro ao buscar dados do usuário no MongoDB + return c.JSON(http.StatusBadRequest, map[string]string{ + "result": "error", + "details": "Error finding this UserID.", + }) + } + + // Verificar o formato da resposta (JSON ou texto) + format := c.QueryParam("format") + if format == "json" { + return c.JSON(http.StatusOK, map[string]string{ + "result": "success", + "username": userDataResult.Username, + "ticket": userDataResult.Ticket, + }) + } + + // Resposta em texto simples + msgTicket := fmt.Sprintf("Hey, %s! This is your ticket: %s\n", userDataResult.Username, userDataResult.Ticket) + return c.String(http.StatusOK, msgTicket) } diff --git a/owasp-top10-2021-apps/a1/ecommerce-api/app/server.go b/owasp-top10-2021-apps/a1/ecommerce-api/app/server.go index b274f67c9..9c0cec902 100644 --- a/owasp-top10-2021-apps/a1/ecommerce-api/app/server.go +++ b/owasp-top10-2021-apps/a1/ecommerce-api/app/server.go @@ -5,34 +5,92 @@ import ( "fmt" "html/template" "io" + "net/http" "os" apiContext "github.com/globocom/secDevLabs/owasp-top10-2021-apps/a1/ecommerce-api/app/context" - "github.com/globocom/secDevLabs/owasp-top10-2021-apps/a1/ecommerce-api/app/db" "github.com/globocom/secDevLabs/owasp-top10-2021-apps/a1/ecommerce-api/app/handlers" + "github.com/globocom/secDevLabs/owasp-top10-2021-apps/a1/ecommerce-api/app/db" "github.com/labstack/echo" "github.com/labstack/echo/middleware" + "github.com/dgrijalva/jwt-go" ) // TemplateRegistry defines the template registry struct -// Ref: https://medium.freecodecamp.org/how-to-setup-a-nested-html-template-in-the-go-echo-web-framework-670f16244bb4 type TemplateRegistry struct { templates map[string]*template.Template } -// Render implement e.Renderer interface -// Ref: https://medium.freecodecamp.org/how-to-setup-a-nested-html-template-in-the-go-echo-web-framework-670f16244bb4 +// Render implements e.Renderer interface func (t *TemplateRegistry) Render(w io.Writer, name string, data interface{}, c echo.Context) error { tmpl, ok := t.templates[name] if !ok { - err := errors.New("Template not found -> " + name) - return err + return fmt.Errorf("template not found: %s", name) } return tmpl.ExecuteTemplate(w, "base.html", data) } -func main() { +// Middleware: Checks if a user is authorized for a specific ticket +func isAuthorized(dbInstance *db.DB) echo.MiddlewareFunc { + return func(next echo.HandlerFunc) echo.HandlerFunc { + return func(c echo.Context) error { + user, ok := c.Get("user").(*jwt.Token) + if !ok { + return echo.ErrUnauthorized + } + + claims, ok := user.Claims.(jwt.MapClaims) + if !ok { + return echo.ErrUnauthorized + } + + userID := claims["id"] + ticketID := c.Param("id") + if !userHasAccessToTicket(dbInstance, fmt.Sprintf("%v", userID), ticketID) { + return echo.ErrUnauthorized + } + + return next(c) + } + } +} + +// Checks if a user has access to a specific ticket +func userHasAccessToTicket(dbInstance *db.DB, userID, ticketID string) bool { + hasPermission, err := dbInstance.CheckUserPermission(userID, ticketID) + if err != nil { + return false + } + return hasPermission +} + +// Middleware: Auth checks JWT token +func AuthMiddleware(next echo.HandlerFunc) echo.HandlerFunc { + return func(c echo.Context) error { + token := c.Request().Header.Get("Authorization") + if token == "" { + return c.JSON(http.StatusUnauthorized, map[string]string{"error": "Unauthorized"}) + } + + _, err := parseToken(token) + if err != nil { + return c.JSON(http.StatusUnauthorized, map[string]string{"error": "Invalid token"}) + } + + c.Set("userID", "exampleUserID") // Exemplo simples + return next(c) + } +} +// Simulated token parser +func parseToken(token string) (string, error) { + if token == "valid-token" { + return "user123", nil + } + return "", errors.New("invalid token") +} + +func main() { configAPI := apiContext.GetAPIConfig() if err := checkRequirements(configAPI); err != nil { @@ -40,16 +98,20 @@ func main() { os.Exit(1) } + // Inicializa conexão com o banco de dados + database, err := db.Connect() + if err != nil { + fmt.Printf("Erro ao conectar ao banco de dados: %v\n", err) + os.Exit(1) + } + defer database.Session.Close() + echoInstance := echo.New() echoInstance.HideBanner = true - // Instantiate a template registry with an array of template set - // Ref: https://medium.freecodecamp.org/how-to-setup-a-nested-html-template-in-the-go-echo-web-framework-670f16244bb4 templates := make(map[string]*template.Template) templates["form.html"] = template.Must(template.ParseFiles("views/form.html", "views/base.html")) - echoInstance.Renderer = &TemplateRegistry{ - templates: templates, - } + echoInstance.Renderer = &TemplateRegistry{templates: templates} echoInstance.Use(middleware.Logger()) echoInstance.Use(middleware.Recover()) @@ -57,32 +119,28 @@ func main() { echoInstance.GET("/", handlers.FormPage) echoInstance.GET("/healthcheck", handlers.HealthCheck) - echoInstance.GET("/ticket/:id", handlers.GetTicket) echoInstance.POST("/register", handlers.RegisterUser) echoInstance.POST("/login", handlers.Login) + ticketGroup := echoInstance.Group("/ticket") + ticketGroup.Use(isAuthorized(database)) + ticketGroup.GET("/:id", handlers.GetTicket) + APIport := fmt.Sprintf(":%d", configAPI.APIPort) echoInstance.Logger.Fatal(echoInstance.Start(APIport)) - } func checkRequirements(configAPI *apiContext.APIConfig) error { - - // check if all environment variables are properly set. if err := checkEnvVars(); err != nil { return err } - - // check if MongoDB is accessible and credentials received are working. if err := checkMongoDB(); err != nil { return err } - return nil } func checkEnvVars() error { - envVars := []string{ "MONGO_HOST", "MONGO_DATABASE_NAME", @@ -90,36 +148,24 @@ func checkEnvVars() error { "MONGO_DATABASE_PASSWORD", } - var envIsSet bool - var allEnvIsSet bool - var errorString string - - env := make(map[string]string) - allEnvIsSet = true - for i := 0; i < len(envVars); i++ { - env[envVars[i]], envIsSet = os.LookupEnv(envVars[i]) - if !envIsSet { - errorString = errorString + envVars[i] + " " - allEnvIsSet = false + var missingVars []string + for _, v := range envVars { + if _, exists := os.LookupEnv(v); !exists { + missingVars = append(missingVars, v) } } - if allEnvIsSet == false { - finalError := fmt.Sprintf("check environment variables: %s", errorString) - return errors.New(finalError) + if len(missingVars) > 0 { + return fmt.Errorf("missing environment variables: %v", missingVars) } return nil } func checkMongoDB() error { - _, err := db.Connect() - if err != nil { - mongoError := fmt.Sprintf("check mongoDB: %s", err) - return errors.New(mongoError) + return fmt.Errorf("check MongoDB: %v", err) } - return nil } From 2bf96f2b78a34cc3803554f70fe31553b19157d4 Mon Sep 17 00:00:00 2001 From: meiryleneavelino Date: Wed, 27 Nov 2024 18:03:25 -0300 Subject: [PATCH 6/9] ajustes broken acess control --- .../a1/ecommerce-api/Makefile | 4 +- .../a1/ecommerce-api/app/handlers/handlers.go | 92 +++++++++++-------- .../a1/ecommerce-api/app/server.go | 87 ++++++++++++------ 3 files changed, 114 insertions(+), 69 deletions(-) diff --git a/owasp-top10-2021-apps/a1/ecommerce-api/Makefile b/owasp-top10-2021-apps/a1/ecommerce-api/Makefile index 24da4a39a..411339ca3 100644 --- a/owasp-top10-2021-apps/a1/ecommerce-api/Makefile +++ b/owasp-top10-2021-apps/a1/ecommerce-api/Makefile @@ -47,11 +47,11 @@ lint: ## Runs project using docker-compose compose: compose-down - docker-compose -f deployments/docker-compose.yml -p secdevlabs up -d --build --force-recreate + podman-compose -f deployments/docker-compose.yml -p secdevlabs up -d --build --force-recreate ## Down project using docker-compose compose-down: - docker-compose -f deployments/docker-compose.yml -p secdevlabs down -v --remove-orphans + podman-compose -f deployments/docker-compose.yml -p secdevlabs down -v --remove-orphans ## Generates passwords and set them as environment variables generate-passwords: 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 97afd8422..659220244 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 @@ -8,49 +8,61 @@ import ( "github.com/labstack/echo" ) -// HealthCheck is the heath check function. +// HealthCheck is the health check function. func HealthCheck(c echo.Context) error { return c.String(http.StatusOK, "WORKING\n") } // GetTicket returns the userID ticket. func GetTicket(c echo.Context) error { - // Obter o userID do contexto (definido por um middleware de autenticação) - userIDFromContext := c.Get("userID").(string) // Assumindo que o middleware adiciona userID no contexto - - // Obter o userID da URL - id := c.Param("id") - - // Verificar se o userID autenticado corresponde ao userID fornecido - if userIDFromContext != id { - return c.JSON(http.StatusForbidden, map[string]string{ - "result": "error", - "details": "Access denied. You are not authorized to view this ticket.", - }) - } - - // Consultar o banco de dados com base no userID - userDataQuery := map[string]interface{}{"userID": id} - userDataResult, err := db.GetUserData(userDataQuery) - if err != nil { - // Erro ao buscar dados do usuário no MongoDB - return c.JSON(http.StatusBadRequest, map[string]string{ - "result": "error", - "details": "Error finding this UserID.", - }) - } - - // Verificar o formato da resposta (JSON ou texto) - format := c.QueryParam("format") - if format == "json" { - return c.JSON(http.StatusOK, map[string]string{ - "result": "success", - "username": userDataResult.Username, - "ticket": userDataResult.Ticket, - }) - } - - // Resposta em texto simples - msgTicket := fmt.Sprintf("Hey, %s! This is your ticket: %s\n", userDataResult.Username, userDataResult.Ticket) - return c.String(http.StatusOK, msgTicket) -} + // Obter o userID do contexto + userIDFromContext, ok := c.Get("userID").(string) + if !ok { + return c.JSON(http.StatusUnauthorized, map[string]string{ + "result": "error", + "details": "Invalid user authentication data.", + }) + } + + // Obter o userID da URL + id := c.Param("id") + if id == "" { + return c.JSON(http.StatusBadRequest, map[string]string{ + "result": "error", + "details": "User ID is required.", + }) + } + + // Verificar se o userID autenticado corresponde ao userID fornecido + if userIDFromContext != id { + return c.JSON(http.StatusForbidden, map[string]string{ + "result": "error", + "details": "Access denied. You are not authorized to view this ticket.", + }) + } + + // Consultar o banco de dados com base no userID + userDataQuery := map[string]interface{}{"userID": id} + userDataResult, err := db.GetUserData(userDataQuery) + if err != nil { + c.Logger().Errorf("Error querying user data: %v", err) + return c.JSON(http.StatusInternalServerError, map[string]string{ + "result": "error", + "details": "An internal error occurred. Please try again later.", + }) + } + + // Verificar o formato da resposta + format := c.QueryParam("format") + if format == "json" { + return c.JSON(http.StatusOK, map[string]interface{}{ + "result": "success", + "username": userDataResult.Username, + "ticket": userDataResult.Ticket, + }) + } + + // Resposta em texto simples + msgTicket := fmt.Sprintf("Hey, %s! This is your ticket: %s\n", userDataResult.Username, userDataResult.Ticket) + return c.String(http.StatusOK, msgTicket) +} \ No newline at end of file diff --git a/owasp-top10-2021-apps/a1/ecommerce-api/app/server.go b/owasp-top10-2021-apps/a1/ecommerce-api/app/server.go index 9c0cec902..93a6d5bd4 100644 --- a/owasp-top10-2021-apps/a1/ecommerce-api/app/server.go +++ b/owasp-top10-2021-apps/a1/ecommerce-api/app/server.go @@ -7,6 +7,7 @@ import ( "io" "net/http" "os" + "strings" apiContext "github.com/globocom/secDevLabs/owasp-top10-2021-apps/a1/ecommerce-api/app/context" "github.com/globocom/secDevLabs/owasp-top10-2021-apps/a1/ecommerce-api/app/handlers" @@ -34,27 +35,42 @@ func (t *TemplateRegistry) Render(w io.Writer, name string, data interface{}, c func isAuthorized(dbInstance *db.DB) echo.MiddlewareFunc { return func(next echo.HandlerFunc) echo.HandlerFunc { return func(c echo.Context) error { + // Recuperar o token JWT do contexto user, ok := c.Get("user").(*jwt.Token) if !ok { - return echo.ErrUnauthorized + return echo.ErrUnauthorized // Retorna 401 se o token estiver ausente ou inválido } + // Extrair as claims do token claims, ok := user.Claims.(jwt.MapClaims) if !ok { - return echo.ErrUnauthorized + return echo.ErrUnauthorized // Retorna 401 se as claims não puderem ser extraídas } - userID := claims["id"] + // Garantir que a claim "id" exista + userID, ok := claims["id"].(string) + if !ok { + return echo.ErrUnauthorized // Retorna 401 se o campo "id" não existir ou estiver no formato errado + } + + // Recuperar o ID do ticket da rota ticketID := c.Param("id") - if !userHasAccessToTicket(dbInstance, fmt.Sprintf("%v", userID), ticketID) { - return echo.ErrUnauthorized + if ticketID == "" { + return echo.ErrBadRequest // Retorna 400 se o ticket ID não for informado } + // Verificar permissão no banco de dados + if !userHasAccessToTicket(dbInstance, userID, ticketID) { + return echo.ErrUnauthorized // Retorna 401 se o usuário não tiver permissão + } + + // Prosseguir para o próximo handler return next(c) } } } + // Checks if a user has access to a specific ticket func userHasAccessToTicket(dbInstance *db.DB, userID, ticketID string) bool { hasPermission, err := dbInstance.CheckUserPermission(userID, ticketID) @@ -66,30 +82,44 @@ func userHasAccessToTicket(dbInstance *db.DB, userID, ticketID string) bool { // Middleware: Auth checks JWT token func AuthMiddleware(next echo.HandlerFunc) echo.HandlerFunc { - return func(c echo.Context) error { - token := c.Request().Header.Get("Authorization") - if token == "" { - return c.JSON(http.StatusUnauthorized, map[string]string{"error": "Unauthorized"}) - } - - _, err := parseToken(token) - if err != nil { - return c.JSON(http.StatusUnauthorized, map[string]string{"error": "Invalid token"}) - } - - c.Set("userID", "exampleUserID") // Exemplo simples - return next(c) - } + return func(c echo.Context) error { + tokenHeader := c.Request().Header.Get("Authorization") + if !strings.HasPrefix(tokenHeader, "Bearer ") { + return c.JSON(http.StatusUnauthorized, map[string]string{"error": "Invalid token format"}) + } + + token := strings.TrimPrefix(tokenHeader, "Bearer ") + userID, err := parseToken(token) + if err != nil { + return c.JSON(http.StatusUnauthorized, map[string]string{"error": err.Error()}) + } + + c.Set("userID", userID) + return next(c) + } } -// Simulated token parser func parseToken(token string) (string, error) { - if token == "valid-token" { - return "user123", nil - } - return "", errors.New("invalid token") + parsedToken, err := jwt.Parse(token, func(t *jwt.Token) (interface{}, error) { + return []byte("secretKey"), nil + }) + if err != nil || !parsedToken.Valid { + return "", errors.New("invalid token") + } + + claims, ok := parsedToken.Claims.(jwt.MapClaims) + if !ok { + return "", errors.New("invalid token claims") + } + + userID, ok := claims["id"].(string) + if !ok { + return "", errors.New("invalid user ID in token") + } + return userID, nil } + func main() { configAPI := apiContext.GetAPIConfig() @@ -121,10 +151,13 @@ func main() { echoInstance.GET("/healthcheck", handlers.HealthCheck) echoInstance.POST("/register", handlers.RegisterUser) echoInstance.POST("/login", handlers.Login) - + ticketGroup := echoInstance.Group("/ticket") - ticketGroup.Use(isAuthorized(database)) - ticketGroup.GET("/:id", handlers.GetTicket) + ticketGroup.Use(middleware.JWTWithConfig(middleware.JWTConfig{ + SigningKey: []byte("secretKey"), // Substitua por uma variável de ambiente + })) + ticketGroup.Use(isAuthorized(database)) + ticketGroup.GET("/:id", handlers.GetTicket) APIport := fmt.Sprintf(":%d", configAPI.APIPort) echoInstance.Logger.Fatal(echoInstance.Start(APIport)) From d750a71f327b513d6c5076249933162523a71f27 Mon Sep 17 00:00:00 2001 From: meiryleneavelino Date: Tue, 17 Dec 2024 21:09:12 -0300 Subject: [PATCH 7/9] autenticacao implementada --- .../a1/ecommerce-api/app/db/mongo.go | 62 ++++--- .../a1/ecommerce-api/app/handlers/handlers.go | 64 +++---- .../a1/ecommerce-api/app/handlers/session.go | 6 + .../a1/ecommerce-api/app/server.go | 157 +++++------------- .../a1/ecommerce-api/app/views/base.html | 1 - .../a1/ecommerce-api/app/views/form.html | 8 +- 6 files changed, 115 insertions(+), 183 deletions(-) diff --git a/owasp-top10-2021-apps/a1/ecommerce-api/app/db/mongo.go b/owasp-top10-2021-apps/a1/ecommerce-api/app/db/mongo.go index d5a1d097f..d60a4e5f4 100644 --- a/owasp-top10-2021-apps/a1/ecommerce-api/app/db/mongo.go +++ b/owasp-top10-2021-apps/a1/ecommerce-api/app/db/mongo.go @@ -10,8 +10,7 @@ import ( // Collections names used in MongoDB. var ( - UserCollection = "users" - TicketsCollection = "tickets" // Adicione a coleção de tickets + UserCollection = "users" ) // DB is the struct that represents mongo session. @@ -35,7 +34,6 @@ type Database interface { UpdateAll(query, updateQuery bson.M, collection string) error Upsert(query bson.M, obj interface{}, collection string) (*mgo.ChangeInfo, error) SearchOne(query bson.M, selectors []string, collection string, obj interface{}) error - CheckUserPermission(userID, ticketID string) (bool, error) // Adicionado para refletir a sugestão } var config = &mongoConfig{ @@ -47,6 +45,8 @@ var config = &mongoConfig{ // Connect connects to mongo and returns the session. func Connect() (*DB, error) { + + // fmt.Printf("config:%#v", config) dialInfo := &mgo.DialInfo{ Addrs: []string{config.Address}, Timeout: time.Second * 60, @@ -64,36 +64,31 @@ func Connect() (*DB, error) { return nil, err } + //go autoReconnect(session) + return &DB{Session: session}, nil } -// CheckUserPermission verifies if a user has access to a specific ticket. -func (db *DB) CheckUserPermission(userID, ticketID string) (bool, error) { - session := db.Session.Clone() - defer session.Close() - c := session.DB(config.DatabaseName).C(TicketsCollection) - - query := bson.M{ - "userID": userID, - "ticketID": ticketID, - } - - var result bson.M - err := c.Find(query).One(&result) - if err != nil { - if err == mgo.ErrNotFound { - return false, nil +// autoReconnect checks mongo's connection each second and, if an error is found, reconnect to it. +func autoReconnect(session *mgo.Session) { + var err error + for { + err = session.Ping() + if err != nil { + session.Refresh() + err = session.Ping() + if err == nil { + } else { + } } - return false, err + time.Sleep(time.Second * 1) } - - return true, nil } // Insert inserts a new document. func (db *DB) Insert(obj interface{}, collection string) error { session := db.Session.Clone() - c := session.DB(config.DatabaseName).C(collection) + c := session.DB("").C(collection) defer session.Close() return c.Insert(obj) } @@ -101,25 +96,26 @@ func (db *DB) Insert(obj interface{}, collection string) error { // Update updates a single document. func (db *DB) Update(query, updateQuery interface{}, collection string) error { session := db.Session.Clone() - c := session.DB(config.DatabaseName).C(collection) + c := session.DB("").C(collection) defer session.Close() - return c.Update(query, updateQuery) + err := c.Update(query, updateQuery) + return err } // UpdateAll updates all documents that match the query. -func (db *DB) UpdateAll(query, updateQuery bson.M, collection string) error { +func (db *DB) UpdateAll(query, updateQuery interface{}, collection string) error { session := db.Session.Clone() - c := session.DB(config.DatabaseName).C(collection) + c := session.DB("").C(collection) defer session.Close() _, err := c.UpdateAll(query, updateQuery) return err } -// Search searches all documents that match the query. If selectors are present, the return will be only the chosen fields. +// Search searchs all documents that match the query. If selectors are present, the return will be only the chosen fields. func (db *DB) Search(query bson.M, selectors []string, collection string, obj interface{}) error { session := db.Session.Clone() defer session.Close() - c := session.DB(config.DatabaseName).C(collection) + c := session.DB("").C(collection) var err error if selectors != nil { @@ -137,11 +133,11 @@ func (db *DB) Search(query bson.M, selectors []string, collection string, obj in return err } -// SearchOne searches for the first element that matches with the given query. +// SearchOne searchs for the first element that matchs with the given query. func (db *DB) SearchOne(query bson.M, selectors []string, collection string, obj interface{}) error { session := db.Session.Clone() defer session.Close() - c := session.DB(config.DatabaseName).C(collection) + c := session.DB("").C(collection) var err error if selectors != nil { @@ -159,10 +155,10 @@ func (db *DB) SearchOne(query bson.M, selectors []string, collection string, obj return err } -// Upsert inserts a document or updates it if it already exists. +// Upsert inserts a document or update it if it already exists. func (db *DB) Upsert(query bson.M, obj interface{}, collection string) (*mgo.ChangeInfo, error) { session := db.Session.Clone() - c := session.DB(config.DatabaseName).C(collection) + c := session.DB("").C(collection) defer session.Close() return c.Upsert(query, obj) } 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 659220244..abaa5b037 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 @@ -4,65 +4,69 @@ import ( "fmt" "net/http" + + "github.com/globocom/secDevLabs/owasp-top10-2021-apps/a1/ecommerce-api/app/db" "github.com/labstack/echo" + jwt "github.com/dgrijalva/jwt-go" ) -// HealthCheck is the health check function. +// HealthCheck is the heath check function. func HealthCheck(c echo.Context) error { return c.String(http.StatusOK, "WORKING\n") } // GetTicket returns the userID ticket. func GetTicket(c echo.Context) error { - // Obter o userID do contexto - userIDFromContext, ok := c.Get("userID").(string) - if !ok { - return c.JSON(http.StatusUnauthorized, map[string]string{ - "result": "error", - "details": "Invalid user authentication data.", - }) - } - // Obter o userID da URL + authHeader := c.Request().Header.Get("Authorization") id := c.Param("id") - if id == "" { - return c.JSON(http.StatusBadRequest, map[string]string{ - "result": "error", - "details": "User ID is required.", - }) - } - // Verificar se o userID autenticado corresponde ao userID fornecido - if userIDFromContext != id { - return c.JSON(http.StatusForbidden, map[string]string{ - "result": "error", - "details": "Access denied. You are not authorized to view this ticket.", + if authHeader == "" { + return c.JSON(http.StatusUnauthorized, map[string]string{ + "error": "Authorization header is missing", }) } - // Consultar o banco de dados com base no userID userDataQuery := map[string]interface{}{"userID": id} userDataResult, err := db.GetUserData(userDataQuery) if err != nil { - c.Logger().Errorf("Error querying user data: %v", err) - return c.JSON(http.StatusInternalServerError, map[string]string{ - "result": "error", - "details": "An internal error occurred. Please try again later.", - }) + // 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."}) } - // Verificar o formato da resposta + format := c.QueryParam("format") if format == "json" { - return c.JSON(http.StatusOK, map[string]interface{}{ + return c.JSON(http.StatusOK, map[string]string{ "result": "success", "username": userDataResult.Username, + "userId" : userDataResult.UserID, "ticket": userDataResult.Ticket, }) } - // Resposta em texto simples msgTicket := fmt.Sprintf("Hey, %s! This is your ticket: %s\n", userDataResult.Username, userDataResult.Ticket) return c.String(http.StatusOK, msgTicket) +} + + +func parseToken(tokenString string) (*Claims, error) { + claims := &Claims{} + // Exemplo de parsing do JWT + token, err := jwt.ParseWithClaims(tokenString, claims, func(token *jwt.Token) (interface{}, error) { + return []byte("secret"), nil // sua chave secreta + }) + + if err != nil || !token.Valid { + return nil, fmt.Errorf("invalid token") + } + + return claims, nil +} + +// Claims define os dados que estarão no JWT +type Claims struct { + UserID string `json:"userId"` + jwt.StandardClaims } \ No newline at end of file diff --git a/owasp-top10-2021-apps/a1/ecommerce-api/app/handlers/session.go b/owasp-top10-2021-apps/a1/ecommerce-api/app/handlers/session.go index 952aaad93..977666cd6 100644 --- a/owasp-top10-2021-apps/a1/ecommerce-api/app/handlers/session.go +++ b/owasp-top10-2021-apps/a1/ecommerce-api/app/handlers/session.go @@ -36,6 +36,7 @@ func ReadCookie(c echo.Context) error { // Login checks MongoDB if this user exists and then returns a JWT session cookie. func Login(c echo.Context) error { + loginAttempt := types.LoginAttempt{} err := c.Bind(&loginAttempt) if err != nil { @@ -43,6 +44,7 @@ func Login(c echo.Context) error { } // input validation missing! + userDataQuery := map[string]interface{}{"username": loginAttempt.Username} userDataResult, err := db.GetUserData(userDataQuery) if err != nil { @@ -67,6 +69,8 @@ func Login(c echo.Context) error { // Set claims claims := token.Claims.(jwt.MapClaims) claims["name"] = userDataResult.Username + claims["userId"]= userDataResult.UserID + claims["Ticket"]= userDataResult.Ticket claims["exp"] = time.Now().Add(time.Hour * 72).Unix() // Generate encoded token and send it as response. @@ -86,6 +90,8 @@ func Login(c echo.Context) error { "result": "success", "username": userDataResult.Username, "user_id": userDataResult.UserID, + "Ticket": userDataResult.Ticket, + "token": t, }) } diff --git a/owasp-top10-2021-apps/a1/ecommerce-api/app/server.go b/owasp-top10-2021-apps/a1/ecommerce-api/app/server.go index 93a6d5bd4..b274f67c9 100644 --- a/owasp-top10-2021-apps/a1/ecommerce-api/app/server.go +++ b/owasp-top10-2021-apps/a1/ecommerce-api/app/server.go @@ -5,122 +5,34 @@ import ( "fmt" "html/template" "io" - "net/http" "os" - "strings" apiContext "github.com/globocom/secDevLabs/owasp-top10-2021-apps/a1/ecommerce-api/app/context" - "github.com/globocom/secDevLabs/owasp-top10-2021-apps/a1/ecommerce-api/app/handlers" "github.com/globocom/secDevLabs/owasp-top10-2021-apps/a1/ecommerce-api/app/db" + "github.com/globocom/secDevLabs/owasp-top10-2021-apps/a1/ecommerce-api/app/handlers" "github.com/labstack/echo" "github.com/labstack/echo/middleware" - "github.com/dgrijalva/jwt-go" ) // TemplateRegistry defines the template registry struct +// Ref: https://medium.freecodecamp.org/how-to-setup-a-nested-html-template-in-the-go-echo-web-framework-670f16244bb4 type TemplateRegistry struct { templates map[string]*template.Template } -// Render implements e.Renderer interface +// Render implement e.Renderer interface +// Ref: https://medium.freecodecamp.org/how-to-setup-a-nested-html-template-in-the-go-echo-web-framework-670f16244bb4 func (t *TemplateRegistry) Render(w io.Writer, name string, data interface{}, c echo.Context) error { tmpl, ok := t.templates[name] if !ok { - return fmt.Errorf("template not found: %s", name) + err := errors.New("Template not found -> " + name) + return err } return tmpl.ExecuteTemplate(w, "base.html", data) } -// Middleware: Checks if a user is authorized for a specific ticket -func isAuthorized(dbInstance *db.DB) echo.MiddlewareFunc { - return func(next echo.HandlerFunc) echo.HandlerFunc { - return func(c echo.Context) error { - // Recuperar o token JWT do contexto - user, ok := c.Get("user").(*jwt.Token) - if !ok { - return echo.ErrUnauthorized // Retorna 401 se o token estiver ausente ou inválido - } - - // Extrair as claims do token - claims, ok := user.Claims.(jwt.MapClaims) - if !ok { - return echo.ErrUnauthorized // Retorna 401 se as claims não puderem ser extraídas - } - - // Garantir que a claim "id" exista - userID, ok := claims["id"].(string) - if !ok { - return echo.ErrUnauthorized // Retorna 401 se o campo "id" não existir ou estiver no formato errado - } - - // Recuperar o ID do ticket da rota - ticketID := c.Param("id") - if ticketID == "" { - return echo.ErrBadRequest // Retorna 400 se o ticket ID não for informado - } - - // Verificar permissão no banco de dados - if !userHasAccessToTicket(dbInstance, userID, ticketID) { - return echo.ErrUnauthorized // Retorna 401 se o usuário não tiver permissão - } - - // Prosseguir para o próximo handler - return next(c) - } - } -} - - -// Checks if a user has access to a specific ticket -func userHasAccessToTicket(dbInstance *db.DB, userID, ticketID string) bool { - hasPermission, err := dbInstance.CheckUserPermission(userID, ticketID) - if err != nil { - return false - } - return hasPermission -} - -// Middleware: Auth checks JWT token -func AuthMiddleware(next echo.HandlerFunc) echo.HandlerFunc { - return func(c echo.Context) error { - tokenHeader := c.Request().Header.Get("Authorization") - if !strings.HasPrefix(tokenHeader, "Bearer ") { - return c.JSON(http.StatusUnauthorized, map[string]string{"error": "Invalid token format"}) - } - - token := strings.TrimPrefix(tokenHeader, "Bearer ") - userID, err := parseToken(token) - if err != nil { - return c.JSON(http.StatusUnauthorized, map[string]string{"error": err.Error()}) - } - - c.Set("userID", userID) - return next(c) - } -} - -func parseToken(token string) (string, error) { - parsedToken, err := jwt.Parse(token, func(t *jwt.Token) (interface{}, error) { - return []byte("secretKey"), nil - }) - if err != nil || !parsedToken.Valid { - return "", errors.New("invalid token") - } - - claims, ok := parsedToken.Claims.(jwt.MapClaims) - if !ok { - return "", errors.New("invalid token claims") - } - - userID, ok := claims["id"].(string) - if !ok { - return "", errors.New("invalid user ID in token") - } - return userID, nil -} - - func main() { + configAPI := apiContext.GetAPIConfig() if err := checkRequirements(configAPI); err != nil { @@ -128,20 +40,16 @@ func main() { os.Exit(1) } - // Inicializa conexão com o banco de dados - database, err := db.Connect() - if err != nil { - fmt.Printf("Erro ao conectar ao banco de dados: %v\n", err) - os.Exit(1) - } - defer database.Session.Close() - echoInstance := echo.New() echoInstance.HideBanner = true + // Instantiate a template registry with an array of template set + // Ref: https://medium.freecodecamp.org/how-to-setup-a-nested-html-template-in-the-go-echo-web-framework-670f16244bb4 templates := make(map[string]*template.Template) templates["form.html"] = template.Must(template.ParseFiles("views/form.html", "views/base.html")) - echoInstance.Renderer = &TemplateRegistry{templates: templates} + echoInstance.Renderer = &TemplateRegistry{ + templates: templates, + } echoInstance.Use(middleware.Logger()) echoInstance.Use(middleware.Recover()) @@ -149,31 +57,32 @@ func main() { echoInstance.GET("/", handlers.FormPage) echoInstance.GET("/healthcheck", handlers.HealthCheck) + echoInstance.GET("/ticket/:id", handlers.GetTicket) echoInstance.POST("/register", handlers.RegisterUser) echoInstance.POST("/login", handlers.Login) - - ticketGroup := echoInstance.Group("/ticket") - ticketGroup.Use(middleware.JWTWithConfig(middleware.JWTConfig{ - SigningKey: []byte("secretKey"), // Substitua por uma variável de ambiente - })) - ticketGroup.Use(isAuthorized(database)) - ticketGroup.GET("/:id", handlers.GetTicket) APIport := fmt.Sprintf(":%d", configAPI.APIPort) echoInstance.Logger.Fatal(echoInstance.Start(APIport)) + } func checkRequirements(configAPI *apiContext.APIConfig) error { + + // check if all environment variables are properly set. if err := checkEnvVars(); err != nil { return err } + + // check if MongoDB is accessible and credentials received are working. if err := checkMongoDB(); err != nil { return err } + return nil } func checkEnvVars() error { + envVars := []string{ "MONGO_HOST", "MONGO_DATABASE_NAME", @@ -181,24 +90,36 @@ func checkEnvVars() error { "MONGO_DATABASE_PASSWORD", } - var missingVars []string - for _, v := range envVars { - if _, exists := os.LookupEnv(v); !exists { - missingVars = append(missingVars, v) + var envIsSet bool + var allEnvIsSet bool + var errorString string + + env := make(map[string]string) + allEnvIsSet = true + for i := 0; i < len(envVars); i++ { + env[envVars[i]], envIsSet = os.LookupEnv(envVars[i]) + if !envIsSet { + errorString = errorString + envVars[i] + " " + allEnvIsSet = false } } - if len(missingVars) > 0 { - return fmt.Errorf("missing environment variables: %v", missingVars) + if allEnvIsSet == false { + finalError := fmt.Sprintf("check environment variables: %s", errorString) + return errors.New(finalError) } return nil } func checkMongoDB() error { + _, err := db.Connect() + if err != nil { - return fmt.Errorf("check MongoDB: %v", err) + mongoError := fmt.Sprintf("check mongoDB: %s", err) + return errors.New(mongoError) } + return nil } diff --git a/owasp-top10-2021-apps/a1/ecommerce-api/app/views/base.html b/owasp-top10-2021-apps/a1/ecommerce-api/app/views/base.html index 330272a35..7b137133c 100644 --- a/owasp-top10-2021-apps/a1/ecommerce-api/app/views/base.html +++ b/owasp-top10-2021-apps/a1/ecommerce-api/app/views/base.html @@ -37,4 +37,3 @@ {{end}} - diff --git a/owasp-top10-2021-apps/a1/ecommerce-api/app/views/form.html b/owasp-top10-2021-apps/a1/ecommerce-api/app/views/form.html index c87fd4069..90b460b68 100644 --- a/owasp-top10-2021-apps/a1/ecommerce-api/app/views/form.html +++ b/owasp-top10-2021-apps/a1/ecommerce-api/app/views/form.html @@ -87,8 +87,11 @@

{{index . "name"}}

XHR.onreadystatechange = function (event) { if (XHR.readyState == 4) { if (XHR.status == 200) { - document.getElementById('page-title').innerHTML = "Your orders" var jsonResponse = JSON.parse(XHR.responseText); + localStorage.setItem('auth_token', jsonResponse.token); + document.getElementById('page-title').innerHTML = "Your orders" + + console.log(jsonResponse) // get ticket's user var XHRticket = new XMLHttpRequest(); @@ -96,6 +99,7 @@

{{index . "name"}}

if (XHRticket.readyState == 4) { if (XHRticket.status == 200) { var jsonTicket = JSON.parse(XHRticket.responseText); + console.log(jsonTicket) document.getElementById('container-form').innerHTML = `
@@ -124,6 +128,8 @@

{{index . "name"}}

}; XHRticket.open('GET', '//localhost:10005/ticket/'+jsonResponse["user_id"]+'?format=json'); XHRticket.setRequestHeader('Content-Type','application/json' ); + XHRticket.setRequestHeader('Authorization', 'Bearer ' + jsonResponse.token); + XHRticket.send(); } else { // Define what happens in case of error From 781b45ca6370d969568b2f63f864171088153472 Mon Sep 17 00:00:00 2001 From: meiryleneavelino Date: Fri, 7 Feb 2025 20:14:12 -0300 Subject: [PATCH 8/9] SnakePro-MSolution --- owasp-top10-2021-apps/a2/snake-pro/Makefile | 4 +- .../a2/snake-pro/app/api/routes.go | 45 +++++++++++-- .../a2/snake-pro/app/cert.pem | 35 ++++++++++ .../a2/snake-pro/app/key.pem | 52 ++++++++++++++ .../a2/snake-pro/app/main.go | 67 +++++++++++++------ .../a2/snake-pro/app/views/form.html | 10 ++- 6 files changed, 180 insertions(+), 33 deletions(-) create mode 100644 owasp-top10-2021-apps/a2/snake-pro/app/cert.pem create mode 100644 owasp-top10-2021-apps/a2/snake-pro/app/key.pem diff --git a/owasp-top10-2021-apps/a2/snake-pro/Makefile b/owasp-top10-2021-apps/a2/snake-pro/Makefile index 00c708b24..0a5952b17 100644 --- a/owasp-top10-2021-apps/a2/snake-pro/Makefile +++ b/owasp-top10-2021-apps/a2/snake-pro/Makefile @@ -23,11 +23,11 @@ install: compose msg ## Composes project using docker-compose compose: compose-down - docker-compose -f deployments/docker-compose.yml -p secdevlabs up -d --build --force-recreate + podman-compose -f deployments/docker-compose.yml -p secdevlabs up -d --build --force-recreate ## Down project using docker-compose compose-down: - docker-compose -f deployments/docker-compose.yml -p secdevlabs down -v --remove-orphans + podman-compose -f deployments/docker-compose.yml -p secdevlabs down -v --remove-orphans ## Prints initialization message after compose phase msg: diff --git a/owasp-top10-2021-apps/a2/snake-pro/app/api/routes.go b/owasp-top10-2021-apps/a2/snake-pro/app/api/routes.go index f614cfac3..7f99eb87b 100644 --- a/owasp-top10-2021-apps/a2/snake-pro/app/api/routes.go +++ b/owasp-top10-2021-apps/a2/snake-pro/app/api/routes.go @@ -2,13 +2,15 @@ package api import ( "fmt" + "log" "net/http" "os" "time" + "golang.org/x/crypto/bcrypt" + jwt "github.com/dgrijalva/jwt-go" db "github.com/globocom/secDevLabs/owasp-top10-2021-apps/a2/snake-pro/app/db/mongo" - "github.com/globocom/secDevLabs/owasp-top10-2021-apps/a2/snake-pro/app/pass" "github.com/globocom/secDevLabs/owasp-top10-2021-apps/a2/snake-pro/app/types" "github.com/google/uuid" "github.com/labstack/echo" @@ -23,11 +25,22 @@ func Root(c echo.Context) error { return c.Redirect(302, "/login") } +// Função para gerar hash da senha +func HashSenha(senha string) (string, error) { + hash, err := bcrypt.GenerateFromPassword([]byte(senha), bcrypt.DefaultCost) + if err != nil { + return "", err + } + return string(hash), nil +} + // WriteCookie writes a cookie into echo Context func WriteCookie(c echo.Context, jwt string) error { cookie := new(http.Cookie) cookie.Name = "sessionIDsnake" cookie.Value = jwt + cookie.Secure = true //inclusao meiry + cookie.HttpOnly = true // inclusao meiry c.SetCookie(cookie) return c.String(http.StatusOK, "") } @@ -55,6 +68,16 @@ func Register(c echo.Context) error { return c.JSON(http.StatusBadRequest, map[string]string{"result": "error", "details": "Passwords do not match."}) } + //Gerar o hash antes de salvar no banco + hashedPassword, err := HashSenha(userData.Password) + if err != nil { + log.Println("Erro ao gerar hash da senha:", err) + return c.JSON(http.StatusInternalServerError, map[string]string{"result": "error", "details": "Internal server error."}) + } + + // Substituir a senha original pelo hash antes de salvar + userData.Password = hashedPassword + newGUID1 := uuid.Must(uuid.NewRandom()) userData.UserID = newGUID1.String() userData.HighestScore = 0 @@ -86,10 +109,17 @@ func Login(c echo.Context) error { return c.JSON(http.StatusForbidden, map[string]string{"result": "error", "details": "Error login."}) } - validPass := pass.CheckPass(userDataResult.Password, loginAttempt.Password) - if !validPass { - // wrong password - return c.JSON(http.StatusForbidden, map[string]string{"result": "error", "details": "Error login."}) + //validPass := pass.CheckPass(userDataResult.Password, loginAttempt.Password) + //if !validPass { + // wrong password + // return c.JSON(http.StatusForbidden, map[string]string{"result": "error", "details": "Error login."}) + //} + + // comparando a senha fornecida com o hash armazenado + err = bcrypt.CompareHashAndPassword([]byte(userDataResult.Password), []byte(loginAttempt.Password)) + if err != nil { + // Se a senha estiver incorreta + return c.JSON(http.StatusForbidden, map[string]string{"result": "error", "details": "Invalid credentials."}) } // Create token @@ -103,15 +133,16 @@ func Login(c echo.Context) error { // Generate encoded token and send it as response. t, err := token.SignedString([]byte(os.Getenv("SECRET_KEY"))) if err != nil { + log.Println("Error generating token:", err) return err } err = WriteCookie(c, t) if err != nil { - return c.JSON(http.StatusBadRequest, map[string]string{"result": "error", "details": "Error login5."}) + return c.JSON(http.StatusBadRequest, map[string]string{"result": "error", "details": "Error writing cookie."}) } c.Response().Header().Set("Content-type", "text/html") messageLogon := fmt.Sprintf("Hello, %s! Welcome to SnakePro", userDataResult.Username) - // err = c.Redirect(http.StatusFound, "http://www.localhost:10003/game/ranking") + // err = c.Redirect(http.StatusFound, "https://www.localhost:10003/game/ranking") return c.String(http.StatusOK, messageLogon) } diff --git a/owasp-top10-2021-apps/a2/snake-pro/app/cert.pem b/owasp-top10-2021-apps/a2/snake-pro/app/cert.pem new file mode 100644 index 000000000..f5a51694f --- /dev/null +++ b/owasp-top10-2021-apps/a2/snake-pro/app/cert.pem @@ -0,0 +1,35 @@ +-----BEGIN CERTIFICATE----- +MIIGITCCBAmgAwIBAgIUVVysXBuhS27Uh948uyGUbLaukmMwDQYJKoZIhvcNAQEL +BQAwgZ8xCzAJBgNVBAYTAkJSMRcwFQYDVQQIDA5SaW8gZGUgSmFuZWlybzEXMBUG +A1UEBwwOUmlvIGRlIEphbmVpcm8xEjAQBgNVBAoMCWxvY2FsaG9zdDESMBAGA1UE +CwwJbG9jYWxob3N0MRIwEAYDVQQDDAlsb2NhbGhvc3QxIjAgBgkqhkiG9w0BCQEW +E3Rlc3RlQGxvY2FsaG9zdC5jb20wHhcNMjUwMjA3MTQyMzQ1WhcNMjYwMjA3MTQy +MzQ1WjCBnzELMAkGA1UEBhMCQlIxFzAVBgNVBAgMDlJpbyBkZSBKYW5laXJvMRcw +FQYDVQQHDA5SaW8gZGUgSmFuZWlybzESMBAGA1UECgwJbG9jYWxob3N0MRIwEAYD +VQQLDAlsb2NhbGhvc3QxEjAQBgNVBAMMCWxvY2FsaG9zdDEiMCAGCSqGSIb3DQEJ +ARYTdGVzdGVAbG9jYWxob3N0LmNvbTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCC +AgoCggIBAKRWIxI2miV0B938t4CSJcf7PFT05DNgVKyQHg8rpy6DmJ5aAs5gcTlw +k/OLSO34zRFsCf8Sz7Q0idmDhCBx596nDfszIVfAg75b7DsjOdt03ovkrYK/F6zA +LGXtUuZAkbcEIvpFxSurGJKbV02IUTHnoW+UAeBVfHS0EmxGLDZvIrmweVUJ11/f +qv+0MKw7gulLRWXD/310pMP0FAfiqlaiez6sUA6oqwtTXeRx3bYLn8lcRh3SiJJN +2iFVl4aP45/HyKkKGn4DzULEYoEjK9jm6ef/2c4ysqnTFulVpZ2jZKw1M+h8NQCF +Cyuri+C+gEY1uDTJBCjcWyVjTkYstjxV/dDVWPgvkjOP29xIn9nk0AjJTo6wYNFt +Y8QfiG0g2LwrnMq/2riBQOAw1Bhlifj2G0QSowRRdFWAcBniDMTQOUolmub84qb5 +2MjQuhhOsxRgQ+7Tc9NDIavXg1zdkfTdDd6RceKEjvt/S+m32ap7SKigTUwp+0Sy +lQPj9a7s7dyTJkzRrrzren9wbxerMnB23Kmeux4+AKsYY8WMe4+PSRoJy8I4CNpG +E9740Ol96FJE7Z6BRqv/LL1i7d8HIgC8Y7iLvKu6DELyStlcfWX7lweAw7Ul9jAb +gtRQ4g3vID0jzRnZE1tj8JpPzARmtyxexpYffoQWU1OYqYBjoNUBAgMBAAGjUzBR +MB0GA1UdDgQWBBTeMra7Wqa3EHQhetg7LwKYeRHOoDAfBgNVHSMEGDAWgBTeMra7 +Wqa3EHQhetg7LwKYeRHOoDAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBCwUA +A4ICAQBSp8HYDX05gARjK2ahtRymUXF8lWqCxjwypCV5nsI2acK3DrpVgQk5zSEF +EouK/uRHxsAU71t3+4nx8LQmopv/vvtJgv4qwcOTmxgasIbbUbvCtlN0UhRBUf/H +raXM23YYk378vQgxnwhPYGmJ3v6OdOl4fEhT32aMMSxb/KPKFQYgobbX8IsidhKP +70DKIL+5inEA/4c4nLMSYLXYVrP/ggTIFXiD1hdgOy6h+TZbGaMeYKIECejPNALd +3BbZ1bVFk4p+eDzugSY/NHXWzR+nuKyD3MHSW9C9xQfLfy7qMzd/S4Y09LBh65Dx +3XlzDXrkMXzIspT6xBJoPIjjZaVhm7CJRcxKQ85iKadYFMNnMFuRyPca5mfK/Jtv +kGZGV6Hk7kFRA8k9jL2x8esge4rCDmZfbtI7tSZc30mgl201KSXq3HblqhuBK6sD +OS5gacU8888RmP012kiXu6Rj/EtR1iRJtwmTsAL+t8UirNXdriSexLO6L8n1ifKf +UUFmiphn0e/eXP6Ke0tUfuVzY9cJdKLEqXqUIUAYMU71JZMdzATWSgdzAF2wucO9 +jwkSwGhhIMs83HSdx+301eC846TvOfBOIJJFE1dyW9uobt0XAaiXDN/S20U0MofE +vQM42BM8orkJEU/eXC4v0cxrumSLAMm+G5PKcn2PiA3mgE2OnA== +-----END CERTIFICATE----- diff --git a/owasp-top10-2021-apps/a2/snake-pro/app/key.pem b/owasp-top10-2021-apps/a2/snake-pro/app/key.pem new file mode 100644 index 000000000..dee75d304 --- /dev/null +++ b/owasp-top10-2021-apps/a2/snake-pro/app/key.pem @@ -0,0 +1,52 @@ +-----BEGIN PRIVATE KEY----- +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 +uSsXujU5+mC+Fu2Q28BTumc1adAGRA== +-----END PRIVATE KEY----- diff --git a/owasp-top10-2021-apps/a2/snake-pro/app/main.go b/owasp-top10-2021-apps/a2/snake-pro/app/main.go index 37e6ec744..868c4bb20 100644 --- a/owasp-top10-2021-apps/a2/snake-pro/app/main.go +++ b/owasp-top10-2021-apps/a2/snake-pro/app/main.go @@ -5,6 +5,8 @@ import ( "fmt" "html/template" "io" + "log" + "net/http" "os" "strconv" @@ -33,11 +35,15 @@ func (t *TemplateRegistry) Render(w io.Writer, name string, data interface{}, c return tmpl.ExecuteTemplate(w, "base.html", data) } -func main() { +// Função para redirecionar HTTP para HTTPS +func redirectToHTTPS(w http.ResponseWriter, r *http.Request) { + // Redireciona para HTTPS + http.Redirect(w, r, "https://localhost:10003"+r.RequestURI, http.StatusMovedPermanently) - fmt.Println("[*] Starting Snake Pro...") +} - // loading viper +func main() { + // Carregando configurações com Viper viper.SetConfigName("config") viper.AddConfigPath(".") if err := viper.ReadInConfig(); err != nil { @@ -47,55 +53,73 @@ func main() { errorAPI(err) } - // check if MongoDB is acessible and credentials received are working. + // Verificando conexão com MongoDB if _, err := checkMongoDB(); err != nil { - fmt.Println("[X] ERROR MONGODB: ", err) + fmt.Println("[X] ERRO MONGODB: ", err) os.Exit(1) } - fmt.Println("[*] MongoDB: OK!") - fmt.Println("[*] Viper loaded: OK!") - + // Configuração do Echo echoInstance := echo.New() echoInstance.HideBanner = true + // Middleware echoInstance.Use(middleware.Logger()) echoInstance.Use(middleware.Recover()) echoInstance.Use(middleware.RequestID()) - templates := make(map[string]*template.Template) - templates["form.html"] = template.Must(template.ParseFiles("views/form.html", "views/base.html")) - templates["game.html"] = template.Must(template.ParseFiles("views/game.html", "views/base.html")) - templates["ranking.html"] = template.Must(template.ParseFiles("views/ranking.html", "views/base.html")) - - echoInstance.Renderer = &TemplateRegistry{ - templates: templates, + // Configuração de templates + templates := map[string]*template.Template{ + "form.html": template.Must(template.ParseFiles("views/form.html", "views/base.html")), + "game.html": template.Must(template.ParseFiles("views/game.html", "views/base.html")), + "ranking.html": template.Must(template.ParseFiles("views/ranking.html", "views/base.html")), } + echoInstance.Renderer = &TemplateRegistry{templates: templates} + + // Rotas públicas echoInstance.GET("/healthcheck", api.HealthCheck) echoInstance.POST("/register", api.Register) echoInstance.POST("/login", api.Login) echoInstance.GET("/login", api.PageLogin) echoInstance.GET("/", api.Root) + + // Rotas protegidas com JWT r := echoInstance.Group("/game") - config := middleware.JWTConfig{ + jwtConfig := middleware.JWTConfig{ TokenLookup: "cookie:sessionIDsnake", SigningKey: []byte(os.Getenv("SECRET_KEY")), } - r.Use(middleware.JWTWithConfig(config)) - + r.Use(middleware.JWTWithConfig(jwtConfig)) r.GET("/play", api.PageGame) r.GET("/ranking", api.PageRanking) + // Servidor HTTP para redirecionar para HTTPS + go func() { + log.Println("Servidor HTTP rodando em http://localhost:8080, redirecionando para HTTPS") + if err := http.ListenAndServe(":8080", http.HandlerFunc(redirectToHTTPS)); err != nil { + log.Fatal("Erro ao iniciar servidor HTTP:", err) + } + }() + + // Pegando a porta da API (padrão: 10003) APIport := fmt.Sprintf(":%d", getAPIPort()) - echoInstance.Logger.Fatal(echoInstance.Start(APIport)) + + // Iniciando o servidor HTTPS corretamente com certificados + log.Println("Servidor HTTPS rodando em https://localhost" + APIport) + err := echoInstance.StartTLS(APIport, "cert.pem", "key.pem") + if err != nil { + log.Fatal("Erro ao iniciar servidor HTTPS:", err) + } } +// Função para tratar erros na inicialização func errorAPI(err error) { - fmt.Println("[x] Error starting Snake Pro:") - fmt.Println("[x]", err) + fmt.Println("[X] Erro ao iniciar Snake Pro:") + fmt.Println("[X]", err) os.Exit(1) } +// Obtém a porta da API, padrão 10003 se não definida func getAPIPort() int { apiPort, err := strconv.Atoi(os.Getenv("API_PORT")) if err != nil { @@ -104,6 +128,7 @@ func getAPIPort() int { return apiPort } +// Verifica conexão com MongoDB func checkMongoDB() (*db.DB, error) { return db.Connect() } diff --git a/owasp-top10-2021-apps/a2/snake-pro/app/views/form.html b/owasp-top10-2021-apps/a2/snake-pro/app/views/form.html index f0f80966e..e0594cce7 100644 --- a/owasp-top10-2021-apps/a2/snake-pro/app/views/form.html +++ b/owasp-top10-2021-apps/a2/snake-pro/app/views/form.html @@ -74,6 +74,7 @@

{{index . "name"}}

+ -{{end}} +{{end}} \ No newline at end of file From 7ec264625507b1cbed1b715ad1dbbd2987971a35 Mon Sep 17 00:00:00 2001 From: meiryleneavelino Date: Fri, 7 Feb 2025 20:47:18 -0300 Subject: [PATCH 9/9] snake-pro-msolution --- owasp-top10-2021-apps/a2/snake-pro/app/api/routes.go | 2 +- owasp-top10-2021-apps/a2/snake-pro/app/views/form.html | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/owasp-top10-2021-apps/a2/snake-pro/app/api/routes.go b/owasp-top10-2021-apps/a2/snake-pro/app/api/routes.go index 7f99eb87b..3b02b059c 100644 --- a/owasp-top10-2021-apps/a2/snake-pro/app/api/routes.go +++ b/owasp-top10-2021-apps/a2/snake-pro/app/api/routes.go @@ -112,7 +112,7 @@ func Login(c echo.Context) error { //validPass := pass.CheckPass(userDataResult.Password, loginAttempt.Password) //if !validPass { // wrong password - // return c.JSON(http.StatusForbidden, map[string]string{"result": "error", "details": "Error login."}) + // return c.JSON(http.StatusForbidden, map[string]string{"result": "error", "details": "Error login."}) //} // comparando a senha fornecida com o hash armazenado diff --git a/owasp-top10-2021-apps/a2/snake-pro/app/views/form.html b/owasp-top10-2021-apps/a2/snake-pro/app/views/form.html index e0594cce7..203789fa3 100644 --- a/owasp-top10-2021-apps/a2/snake-pro/app/views/form.html +++ b/owasp-top10-2021-apps/a2/snake-pro/app/views/form.html @@ -143,4 +143,4 @@

{{index . "name"}}

XHR.send(json); }); -{{end}} \ No newline at end of file +{{end}}