HIGH replay attackecho gobasic auth

Replay Attack in Echo Go with Basic Auth

Replay Attack in Echo Go with Basic Auth — how this specific combination creates or exposes the vulnerability

A replay attack in the Echo Go framework using HTTP Basic Auth occurs when an attacker captures a valid authentication exchange (request + credentials) and re-sends it to impersonate the original client. Basic Auth transmits credentials in an Authorization header encoded as Base64 (not encrypted). If the channel lacks strong transport-layer protections or the server does not enforce per-request nonces/timestamps, an intercepted request can be replayed with high likelihood of success.

In Echo Go, this risk is amplified when endpoints rely solely on Basic Auth for authorization without additional anti-replay controls. For example, an authentication route that only validates the username/password pair on each request will accept a replayed header because the credentials remain valid. Without mechanisms such as server-side nonces, one-time tokens, or strict timestamp validation, the session token or the fact that the client is authorized becomes the replay target. Attackers can capture traffic on insecure networks or via compromised intermediaries and re-inject the captured Authorization header to gain unauthorized access to protected resources, potentially leading to privilege escalation or data exposure.

Consider an endpoint that does not bind authentication to request context (e.g., method, path, timestamp). A captured request to POST /transfer with a valid Basic Auth header can be replayed to initiate another transfer. Because the server treats each request independently and only verifies the encoded credentials, the replay succeeds. This is a classic authentication replay pitfall: the protocol (Basic Auth over TLS) is sound, but the application-layer implementation in Echo Go does not ensure request uniqueness or freshness.

When scanning an Echo Go API with middleware that uses Basic Auth, middleBrick checks whether authentication is combined with replay-preventive controls. Findings may highlight missing nonce/timestamp validation or lack of replay-resistant session binding, aligning with authentication weaknesses in the OWASP API Top 10. Even when TLS is used, the absence of server-side protections means a replay attack remains feasible if an attacker can obtain or predict a valid Authorization header.

Basic Auth-Specific Remediation in Echo Go — concrete code fixes

Remediation focuses on ensuring that each authenticated request is unique and time-bound. Below are concrete, working examples for Echo Go that combine Basic Auth with server-side nonce or timestamp validation to mitigate replay attacks.

Example 1: Basic Auth with timestamp and server-side nonce validation. The client includes an ISO8601 timestamp and a nonce; the server checks freshness and records used nonces to prevent reuse.

// Client: build Authorization header with timestamp and nonce
package main

import (
	"crypto/rand"
	"encoding/base64"
	"fmt"
	"net/http"
	"time"
)

func basicAuthWithNonce(user, pass string) string {
	nonce := make([]byte, 16)
	rand.Read(nonce)
	nonceStr := base64.StdEncoding.EncodeToString(nonce)
	timestamp := time.Now().UTC().Format(time.RFC3339)
	// credentials are user:pass
	auth := user + ":" + pass
	return base64.StdEncoding.EncodeToString([]byte(auth)) + "," + timestamp + "," + nonceStr
}

func main() {
	req, _ := http.NewRequest("GET", "https://api.example.com/account", nil)
	req.Header.Set("Authorization", "Basic " + basicAuthWithNonce("alice", "s3cret"))
	// send request...
}
// Server: Echo Go middleware to validate timestamp and nonce
package main

import (
	"errors"
	"net/http"
	"strings"
	"time"

	"github.com/labstack/echo/v4"
)

var usedNonces = make(map[string]bool)

func replayProtection(next echo.HandlerFunc) echo.HandlerFunc {
	return func(c echo.Context) error {
		auth := c.Request().Header.Get("Authorization")
		if auth == "" {
			return echo.ErrUnauthorized
		}
		parts := strings.Split(auth, ",")
		if len(parts) != 3 {
			return errors.New("invalid authorization format")
		}
		b64Creds, ts, nonce := parts[0], parts[1], parts[2]
		t, err := time.Parse(time.RFC3339, ts)
		if err != nil || time.Since(t) > 30*time.Second {
			return errors.New("stale timestamp")
		}
		if usedNonces[nonce] {
			return errors.New("replayed nonce detected")
		}
		usedNonces[nonce] = true
		// optionally validate b64Creds against a user store
		return next(c)
	}
}

func handler(c echo.Context) error {
	return c.String(http.StatusOK, "ok")
}

func main() {
	e := echo.New()
	e.Use(replayProtection)
	e.GET("/account", handler)
	e.Start(":8080")
}

Example 2: Use a short-lived server-side session after initial Basic Auth validation. Upon successful username/password verification, issue a one-time token bound to the request context and require it for subsequent calls.

// Initial login with Basic Auth, then issue a one-time token
package main

import (
	"crypto/subtle"
	"net/http"

	"github.com/labstack/echo/v4"
)

var validUser = "alice"
var validPass = "s3cret"
var oneTimeTokens = make(map[string]string) // token -> username

func login(c echo.Context) error {
	auth := c.Request().Header.Get("Authorization")
	if auth == "" {
		return echo.ErrUnauthorized
	}
	// decode "Basic base64(creds)"
	// validate creds (omitted for brevity)
	token := "tok-" + c.Request().Header.Get("X-Client-Nonce") // simplified
	oneTimeTokens[token] = validUser
	return c.JSON(http.StatusOK, map[string]string{"token": token})
}

func protected(c echo.Context) error {
	token := c.Request().Header.Get("X-API-Token")
	if token == "" || subtle.ConstantTimeCompare([]byte(token), []byte("")) == 1 {
		return echo.ErrUnauthorized
	}
	user, ok := oneTimeTokens[token]
	if !ok || subtle.ConstantTimeCompare([]byte(user), []byte(validUser)) != 1 {
		return echo.ErrUnauthorized
	}
	delete(oneTimeTokens, token)
	return c.String(http.StatusOK, "protected")
}

func main() {
	e := echo.New()
	e.POST("/login", login)
	e.Use(func(next echo.HandlerFunc) echo.HandlerFunc {
		return func(c echo.Context) error {
			if c.Path() == "/login" {
				return next(c)
			}
			return protected(c)
		}
	})
	e.GET("/data", func(c echo.Context) error { return c.String(http.StatusOK, "data") })
	e.Start(":8080")
}

Key principles: never rely on Basic Auth alone for replay protection; enforce freshness via timestamps and uniqueness via nonces; bind authentication to request context; invalidate or single-use tokens where applicable. These steps ensure that even if credentials are intercepted, they cannot be reused maliciously.

Frequently Asked Questions

Can Basic Auth be used safely in Echo Go if TLS is enforced?
TLS protects credentials in transit but does not prevent replay attacks. You must add per-request nonces or timestamps in Echo Go to ensure request uniqueness.
How does middleBrick assess replay risk for Basic Auth in Echo Go?
middleBrick checks whether authentication is paired with replay-preventive mechanisms such as nonce/timestamp validation and context binding, highlighting gaps where captured requests could be reused.