HIGH session fixationecho gohmac signatures

Session Fixation in Echo Go with Hmac Signatures

Session Fixation in Echo Go with Hmac Signatures — how this specific combination creates or exposes the vulnerability

Session fixation occurs when an application assigns a user a session identifier before authentication and allows that identifier to persist after login. In Echo Go, if you generate a session token or cookie value once and reuse it after a user authenticates, an attacker can force a victim to use a known session value. Even when you use Hmac Signatures to sign requests or cookies, the fixation vector remains if the signature is bound to the session identifier rather than to a post-authentication secret or per-request context.

Consider an Echo Go handler that creates a cookie and signs it with Hmac Signatures before authentication:

import (
    "crypto/hmac"
    "crypto/sha256"
    "encoding/hex"
    "net/http"
    "github.com/labstack/echo/v4"
)

var key = []byte("super-secret-key-32-bytes-long-for-hmac-sha256")

func sign(data string) string {
    mac := hmac.New(sha256.New, key)
    mac.Write([]byte(data))
    return hex.EncodeToString(mac.Sum(nil))
}

func setSession(c echo.Context, sessionID string) {
    token := sessionID + "." + sign(sessionID)
    cookie := &http.Cookie{
        Name:     "session_token",
        Value:    token,
        HttpOnly: true,
        Path:     "/",
    }
    http.SetCookie(c.Response(), cookie)
}

func loginHandler(c echo.Context) error {
    // Dangerous: session created before authentication
    sessionID := c.Request().Header.Get("X-Session-ID")
    if sessionID == "" {
        sessionID = "fixed-value-from-attacker"
    }
    setSession(c, sessionID)
    // ... perform login
    return c.String(http.StatusOK, "logged in")
}

In this pattern, the Hmac Signature covers only the session identifier, which is static and chosen by the attacker. After authentication, the server validates the signature on the same pre-auth session ID, which remains unchanged. An attacker who can get a victim to use a known session ID (e.g., via a link or embedded image) can later hijack the authenticated session because the signature does not incorporate a post-authentication secret or nonce. The signature ensures integrity of the known session ID but does not prevent fixation.

Additionally, if your Echo Go application uses the same Hmac-signed token for both authentication and authorization checks without re-signing after login, an attacker can leverage the fixed session to access protected endpoints. The vulnerability is not in Hmac Signatures themselves but in how the signed value is generated, bound to identity, and rotated after authentication. Without per-session or per-request nonces tied to the authenticated user context, the Hmac signature becomes a static credential that can be reused.

To detect this during a scan, middleBrick tests unauthenticated endpoints and looks for patterns where session identifiers are established before authentication and signatures do not include dynamic, post-login factors. This helps identify whether an API or web flow is susceptible to session fixation despite using cryptographic signing.

Hmac Signatures-Specific Remediation in Echo Go — concrete code fixes

Remediation focuses on ensuring the session identifier is established only after successful authentication and that Hmac Signatures incorporate post-authentication secrets or per-request nonces. Never reuse a pre-authentication session value after login. Instead, generate a new, random session identifier upon login and sign it with a key that may be augmented with user-specific and request-specific data.

Use cryptographically secure random values for session IDs and include contextual data such as user ID, timestamp, and a server-side nonce when computing the Hmac signature. Rotate the signing key periodically and avoid exposing raw session IDs in URLs.

Secure Echo Go login handler example with Hmac Signatures:

import (
    "crypto/hmac"
    "crypto/rand"
    "crypto/sha256"
    "encoding/hex"
    "errors"
    "net/http"
    "time"
    "github.com/labstack/echo/v4"
)

var key = []byte("super-secret-key-32-bytes-long-for-hmac-sha256")

func generateSessionID() (string, error) {
    b := make([]byte, 32)
    _, err := rand.Read(b)
    if err != nil {
        return "", err
    }
    return hex.EncodeToString(b), nil
}

func sign(data string, extra string) string {
    mac := hmac.New(sha256.New, key)
    mac.Write([]byte(data))
    mac.Write([]byte(extra))
    return hex.EncodeToString(mac.Sum(nil))
}

func setSession(c echo.Context, sessionID, userID string) {
    // Include user context and timestamp to bind signature to authenticated state
    ts := strconv.FormatInt(time.Now().Unix(), 10)
    token := sessionID + "." + userID + "." + ts + "." + sign(sessionID+userID+ts, "auth-bound")
    cookie := &http.Cookie{
        Name:     "session_token",
        Value:    token,
        HttpOnly: true,
        Secure:   true,
        SameSite: http.SameSiteStrictMode,
        Path:     "/",
    }
    http.SetCookie(c.Response(), cookie)
}

func loginHandler(c echo.Context) error {
    // Perform authentication (validate credentials)
    userID, err := authenticate(c)
    if err != nil {
        return c.String(http.StatusUnauthorized, "invalid credentials")
    }
    // Generate fresh session after authentication
    sessionID, err := generateSessionID()
    if err != nil {
        return c.String(http.StatusInternalServerError, "server error")
    }
    setSession(c, sessionID, userID)
    return c.String(http.StatusOK, "logged in")
}

func authenticate(c echo.Context) (string, error) {
    // Example: validate username/password from request body
    var creds struct {
        Username string `json:"username"`
        Password string `json:"password"`
    }
    if err := c.Bind(&creds); err != nil {
        return "", err
    }
    // Replace with real user lookup and password verification
    if creds.Username == "alice" && creds.Password == "correct-horse-battery-staple" {
        return "user-123", nil
    }
    return "", errors.New("auth failed")
}

In this approach, the session ID is random and generated after authentication. The Hmac signature covers session ID, user ID, timestamp, and a static binding string, ensuring that the token cannot be reused across users or sessions. The server should validate incoming tokens by recomputing the signature using stored or contextual data and reject tokens with mismatches or replayed timestamps.

When using middleBrick, scans will flag pre-authentication session creation and static signed tokens as high-risk findings. The scanner does not fix these but provides remediation guidance aligned with secure session management practices and OWASP API Top 10 references.

Frequently Asked Questions

Can middleBrick detect session fixation in Echo Go APIs that use Hmac Signatures?
Yes, middleBrick scans unauthenticated attack surfaces and flags patterns where session identifiers are established before authentication, even when Hmac Signatures are used. It reports findings with severity and remediation guidance but does not fix the issue.
Does using Hmac Signatures alone prevent session fixation in Echo Go?
No. Hmac Signatures ensure integrity of the data they cover, but if the signed value is a static session ID established before login, fixation remains possible. Remediation requires generating a fresh session identifier after authentication and binding the signature to post-login context such as user ID and timestamps.