Replay Attack in Fiber with Api Keys
Replay Attack in Fiber with Api Keys
A replay attack in the Fiber HTTP framework becomes feasible when API keys are transmitted or stored in a way that does not include protections against request duplication. In this scenario, an attacker intercepts a valid request that includes an API key in a header, query parameter, or cookie, then re-sends the same request to the endpoint. Because the endpoint validates only the API key and does not enforce additional nonces, timestamps, or idempotency controls, the server treats the replayed request as legitimate.
Consider a Fiber route that relies solely on an API key header for authorization:
package main
import (
"github.com/gofiber/fiber/v2"
"strings"
)
const validKey = "sec_12345abcdef"
func apiKeyAuth(c *fiber.Ctx) error {
provided := c.Get("X-API-Key")
if provided != validKey {
return c.Status(fiber.StatusUnauthorized).JSON(fiber.Map{"error": "unauthorized"})
}
// Business logic vulnerable to replay
return c.JSON(fiber.Map{"status": "ok"})
}
func main() {
app := fiber.New()
app.Get("/resource", apiKeyAuth, func(c *fiber.Ctx) error {
return c.JSON(fiber.Map{"data": "sensitive"})
})
app.Listen(":3000")
}
In this setup, an intercepted X-API-Key: sec_12345abcdef can be reused to replay the request at any time, as there is no mechanism to detect duplication. The API key identifies the client but does not bind the request to a specific context such as a timestamp or a nonce, which enables an attacker to replay payment instructions, state changes, or sensitive data retrieval.
The risk is elevated when requests change server state (POST/PUT/DELETE) and the API key is the only gatekeeper. Even if TLS protects the transmission in transit, captured requests can be replayed before they expire or until the key is rotated. This pattern maps to common weaknesses such as missing replay protections and aligns with broader classes like broken authentication and insufficient anti-automation controls, which are highlighted in the OWASP API Security Top 10.
Api Keys-Specific Remediation in Fiber
To mitigate replay attacks when using API keys in Fiber, combine short-lived keys with request-level context such as timestamps and nonces. The server must validate not only the key but also that the request has not been seen before and is recent.
One approach is to require an additional X-Request-Timestamp and X-Request-Nonce header, and to enforce a tight validity window:
package main
import (
"crypto/sha256"
"encoding/hex"
"fmt"
"net/http"
"strconv"
"time"
"github.com/gofiber/fiber/v2"
)
const validKey = "sec_12345abcdef"
const allowedSkew = 5 * time.Second
func replaySafeAuth(c *fiber.Ctx) error {
providedKey := c.Get("X-API-Key")
if providedKey != validKey {
return c.Status(fiber.StatusUnauthorized).JSON(fiber.Map{"error": "unauthorized"})
}
tsStr := c.Get("X-Request-Timestamp")
if tsStr == "" {
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": "missing timestamp"})
}
ts, err := strconv.ParseInt(tsStr, 10, 64)
if err != nil {
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": "invalid timestamp"})
}
reqTime := time.Unix(ts, 0)
if time.Since(reqTime).Abs() > allowedSkew {
return c.Status(fiber.StatusForbidden).JSON(fiber.Map{"error": "stale request"})
}
nonce := c.Get("X-Request-Nonce")
if nonce == "" {
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": "missing nonce"})
}
// In practice, store seen nonces with TTL matching the skew window
// Example validation (pseudo): if seen(nonce) { reject }
// storeSeen(nonce)
h := sha256.New()
h.Write([]byte(nonce + tsStr + validKey))
expectedMAC := hex.EncodeToString(h.Sum(nil))
// Optionally require client to send MAC of (nonce+timestamp+key) to prove key possession
return c.Next()
}
func main() {
app := fiber.New()
app.Post("/resource", replaySafeAuth, func(c *fiber.Ctx) error {
return c.JSON(fiber.Map{"data": "protected"})
})
app.Listen(":3000")
}
For simpler cases where adding two headers is burdensome, rotate API keys frequently and bind them to IP or user-agent where appropriate. You can also leverage middleware to track recently seen nonces in memory or with a short-lived cache, rejecting duplicates within the skew window. These changes make replayed requests fail because timestamps fall outside the acceptable range or nonces are already consumed.