Replay Attack in Chi with Api Keys
Replay Attack in Chi with Api Keys — how this specific combination creates or exposes the vulnerability
A replay attack in the context of Chi using API keys occurs when an intercepted authenticated request is maliciously reused to impersonate the original sender. Because API keys are typically transmitted in headers and often remain static over time, an attacker who observes a valid request—such as a payment or configuration change—can replay it to perform unauthorized actions without needing to know the secret’s plaintext value. This risk is especially relevant when API calls are made over unencrypted channels or when the same key is used across multiple environments, allowing captured traffic to be replayed in different regions or even different cloud accounts.
Chi, a lightweight HTTP framework, does not inherently provide replay protection, so developers must implement safeguards at the application layer. Without nonces, timestamps, or idempotency mechanisms, an API key alone is insufficient to prevent replay. For example, an intercepted request to POST /v1/transactions with a static key can be replayed hours later, and the server may treat it as legitimate if it only validates the key’s scope and permissions. Attackers can automate this by capturing traffic with tools like tcpdump or via compromised network appliances, then replaying crafted requests at scale.
Real-world scenarios include logging endpoints that accept API keys via header and lack request uniqueness constraints, enabling an attacker to duplicate log submission requests to flood systems or trigger duplicate side effects. In microservice architectures where services communicate using Chi with API keys for mutual authentication, replayed requests can propagate across internal calls, amplifying the impact. The OWASP API Top 10 category ‘2023-A1: Broken Object Level Authorization’ intersects here when replayed requests manipulate object identifiers, and standards like PCI-DSS implicitly require replay resistance for payment-related endpoints. middleBrick’s 12 security checks, including its Input Validation and Rate Limiting scans, can detect missing replay defenses by correlating repeated requests with valid API keys during unauthenticated testing.
Because middleBrick scans in 5–15 seconds without credentials, it can quickly surface whether your Chi endpoints using API keys are vulnerable to replay without requiring access to source code. Its findings include concrete remediation guidance and map to compliance frameworks such as GDPR and SOC2, emphasizing the need for dynamic protections. Note that middleBrick detects and reports these risks but does not fix, patch, or block requests—remediation must be implemented in your application logic.
Api Keys-Specific Remediation in Chi — concrete code fixes
To mitigate replay attacks in Chi when using API keys, you must enforce request uniqueness and freshness. This involves adding a timestamp and a nonce or a one-time token to each request, validating these server-side, and rejecting duplicates or stale requests. Below are concrete examples showing how to implement these protections in Chi middleware and handlers.
Example 1: Adding Timestamp and Nonce to Requests
Clients should generate a unique nonce and current timestamp for each request, signing or including them in headers. This example uses a custom header structure compatible with Chi.
import System.Random (randomRIO)
import Data.Time.Clock (getCurrentTime, UTCTime(..))
import Network.Wai (requestHeaders)
import Network.HTTP.Types (hContentType)
-- Client-side helper to build headers
buildSecureHeaders :: IO [(ByteString, ByteString)]
buildSecureHeaders = do
nonce <- randomString 16
timestamp <- show . utctDayTime <$> getCurrentTime
let apiKey = "your_api_key_here"
let signature = simpleHash (apiKey ++ nonce ++ timestamp)
return [
("X-API-Key", apiKey)
, ("X-Request-Nonce", nonce)
, ("X-Request-Timestamp", timestamp)
, ("X-Request-Signature", signature)
]
randomString :: Int -> IO ByteString
randomString len = do
g <- newStdGen
return $ take len $ unfoldr (Just . randomR ('a','z')) g
simpleHash :: ByteString -> ByteString
simpleHash = ... -- e.g., SHA256 truncated
Example 2: Server-Side Validation in Chi
Server middleware in Chi checks the timestamp window (e.g., 5 minutes) and ensures nonces are not reused. It also verifies the signature to confirm request integrity.
import Network.Wai
import Network.Wai.Middleware.RequestLogger (logStdoutDev)
import qualified Data.ByteString.Lazy as BL
import Data.Time.Clock (getCurrentTime, diffUTCTime)
import Data.Set (Set)
import qualified Data.Set as Set
-- In-memory store for used nonces (use Redis or similar in production)
var nonces :: Set ByteString
replayProtection :: Middleware
replayProtection app req respond = do
now <- getCurrentTime
let nonce = lookup "X-Request-Nonce" (requestHeaders req)
tsStr = lookup "X-Request-Timestamp" (requestHeaders req)
sig = lookup "X-Request-Signature" (requestHeaders req)
apiKey = lookup "X-API-Key" (requestHeaders req)
case (nonce, tsStr, sig, apiKey) of
(Just n, Just ts, Just s, Just key) -> do
let tsInt = read $ unpack ts :: UTCTime
if abs (diffUTCTime now tsInt) > 300
then respond $ responseLBS status400 [] "Request expired"
else if Set.member n nonces
then respond $ responseLBS status403 [] "Duplicate request detected"
else do
let valid = verifySignature key n ts s
if valid
then do
-- Register nonce and proceed
nonces = Set.insert n nonces
app req respond
else respond $ responseLBS status403 [] "Invalid signature"
_ -> respond $ responseLBS status400 [] "Missing security headers"
Example 3: Idempotency Key Pattern
For idempotent operations, include an idempotency key header and store processed keys with their outcomes to safely reject replays.
-- Client includes Idempotency-Key for safe retries
"Idempotency-Key": "req-abc123"
-- Server checks a persistent store before executing side effects
-- Pseudocode:
if store.contains(idempotencyKey) and store.isCompleted(key):
return cachedResponse
else:
processAndStore(key, response)
Using these patterns, you ensure that even if an API key is intercepted, the associated requests cannot be trivially replayed. middleBrick can validate that these headers are present and that endpoints reject repeated nonces, giving you actionable findings and remediation steps mapped to frameworks like OWASP API Top 10.