Cross Site Request Forgery in Echo Go with Mongodb
Cross Site Request Forgery in Echo Go with Mongodb — how this specific combination creates or exposes the vulnerability
Cross Site Request Forgery (CSRF) in an Echo Go API that uses MongoDB can occur when state-changing endpoints rely only on cookies for session-like identification without anti-CSRF protections. In a typical Go web API built with github.com/labstack/echo/v4, if the server sets an authentication cookie after login and subsequent MongoDB operations use that cookie to infer identity, an attacker can craft a malicious site that issues requests on behalf of the victim. Because Echo does not enforce same-site cookie semantics by default and Go’s net/http cookie handling is per-domain, a request initiated from an external site will still include the session cookie if the user is authenticated.
When the handler performs a MongoDB operation based solely on the cookie value (for example, decoding a user ID from the cookie and using it directly in a database query), the attacker can forge actions such as updating or deleting records. A concrete scenario: an endpoint PATCH /users/{id} expects a user ID in the URL and uses the request’s cookie to authorize the update. If the attacker tricks the victim’s browser into sending a forged PATCH /users/1234 with a body that changes the victim’s email, and the handler applies the update after looking up the user ID from the cookie, the malicious update succeeds in MongoDB without any CSRF token validation.
This risk is compounded when the Echo server does not validate the Origin or Referer headers and when MongoDB queries directly reflect user-controlled values without additional context checks. The Echo middleware stack may expose unauthenticated attack surfaces if routes intended for authenticated actions are reachable without explicit checks, allowing an attacker to probe endpoints and discover update patterns. Using the MongoDB Go driver, developers might write queries that filter by user ID taken from the cookie without binding the cookie to a per-request anti-CSRF token, effectively trusting the browser session implicitly.
For example, an Echo route that updates a user document in MongoDB might look like this, illustrating the vulnerability when no CSRF mitigation is applied:
package main
import (
"context"
"net/http"
"go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/mongo"
"go.mongodb.org/mongo-driver/mongo/options"
"github.com/labstack/echo/v4"
)
type UserUpdate struct {
Email string `json:"email"`
}
func updateUser(c echo.Context) error {
client, _ := mongo.Connect(context.TODO(), options.Client().ApplyURI("mongodb://localhost:27017"))
coll := client.Database("appdb").Collection("users")
userID := c.Get("userID").(string) // derived from cookie, no CSRF token
var req UserUpdate
if err := c.Bind(&req); err != nil {
return err
}
_, err := coll.UpdateOne(context.TODO(), bson.M{"_id": userID}, bson.M{"$set": bson.M{"email": req.Email}})
if err != nil {
return c.JSON(http.StatusInternalServerError, map[string]string{"error": "update failed"})
}
return c.JSON(http.StatusOK, map[string]string{"status": "updated"})
}
In this setup, if an attacker forges a request to /users/abc123 with a malicious email, and the cookie is sent automatically, the MongoDB update will apply to the victim’s account. CSRF here is not about authentication bypass but about unauthorized command execution mediated by the trust in session cookies and direct MongoDB updates tied to those cookies.
Mongodb-Specific Remediation in Echo Go — concrete code fixes
Remediation focuses on ensuring that each state-changing MongoDB operation is bound to the authenticated user in a way that cannot be overridden by a forged request, and that CSRF tokens or same-site cookies are used. The following practices reduce risk when using MongoDB with Echo Go:
- Set secure cookie attributes:
Secure,HttpOnly, andSameSite=StrictorLax. This prevents the browser from sending the session cookie in cross-site requests. - Use anti-CSRF tokens for state-changing methods and verify them server-side before executing any MongoDB operation.
- Bind the user identity to the request context in Echo and ensure any MongoDB filter explicitly includes the user ID, rather than relying only on URL parameters that can be tampered with.
Concrete code example with CSRF token verification and safe MongoDB update in Echo Go:
package main
import (
"context"
"net/http"
"go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/mongo"
"go.mongodb.org/mongo-driver/mongo/options"
"github.com/labstack/echo/v4"
"github.com/labstack/echo/v4/middleware"
)
type UserUpdate struct {
Email string `json:"email"`
CsrfToken string `json:"_csrf"`
}
func validateCSRFToken(userID, token string) bool {
// In practice, use a secure token store or signed session token
return token == "expected-csrf-"+userID // simplified example
}
func updateUserSecure(c echo.Context) error {
client, _ := mongo.Connect(context.TODO(), options.Client().ApplyURI("mongodb://localhost:27017"))
coll := client.Database("appdb").Collection("users")
userID := c.Get("userID").(string)
var req UserUpdate
if err := c.Bind(&req); err != nil {
return err
}
if !validateCSRFToken(userID, req.CsrfToken) {
return c.JSON(http.StatusForbidden, map[string]string{"error": "invalid CSRF token"})
}
// Ensure the update targets the same user derived from the session, not the URL parameter alone
_, err := coll.UpdateOne(context.TODO(), bson.M{"_id": userID}, bson.M{"$set": bson.M{"email": req.Email}})
if err != nil {
return c.JSON(http.StatusInternalServerError, map[string]string{"error": "update failed"})
}
return c.JSON(http.StatusOK, map[string]string{"status": "updated"})
}
func main() {
e := echo.New()
e.Use(middleware.CSRFWithConfig(middleware.CSRFConfig{
CookieName: "csrf_token",
CookieSecure: true,
CookieHTTPOnly: true,
CookieSameSite: http.SameSiteStrictMode,
}))
e.POST("/users/:id", updateUserSecure)
e.Start(":8080")
}
Additionally, configure the MongoDB connection to use authentication and role-based access control so that even if an attacker manages to trigger an update, the scope is limited. Combine these measures with input validation and secure session management in Echo to reduce the likelihood of successful CSRF against MongoDB-backed endpoints.