Beyond Static Rules: Catching User-Agent Spoofing at the Edge Without Enterprise WAF

Share
Beyond Static Rules: Catching User-Agent Spoofing at the Edge Without Enterprise WAF

How analyzing HTTP/2 Client Hints anomalies provides enterprise-grade bot detection on standard Cloudflare plans.

1. The Vulnerability of Legacy Layer 7 Rules

In perimeter security, a common initial defensive measure against automated tools like curl, python-requests, or custom scrapers is matching the User-Agent header. A basic WAF rule like (http.user_agent contains "curl") appears to work initially, but it relies on an easily manipulable application-layer string.

From an attacker's perspective, bypassing this control takes seconds by appending a custom header flag:

curl.exe -A "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36" -I https://experiement.xyz

The Edge Telemetry Proof (Bypass)

When executing this spoofed request against a perimeter configured with standard string-matching rules, the WAF evaluates the User-Agent string as a legitimate browser and allows the connection through:

HTTP/1.1 522 Connection Timed Out
Date: Wed, 30 Sep 2026 09:01:45 GMT
Server: cloudflare
CF-RAY: a4320afcefdb4892-LIS
SecOps Note: The HTTP 522 status code confirms that the edge WAF failed to block the request. Cloudflare accepted the request as legitimate traffic and attempted to forward it to the origin IP, where it eventually timed out.

2. Enterprise TLS Fingerprinting vs. Resourceful SecOps

In Enterprise environments, SecOps teams stop header spoofing at Layer 6/7 using TLS Fingerprinting (JA4 or JA3). By inspecting the Client Hello package during the TLS handshake specifically cipher suites, extension lists, and elliptic curves Cloudflare can identify that the underlying binary is curl (OpenSSL/Schannel) regardless of what string it sends in the HTTP payload.

However, fields like cf.ja4 or cf.ja3 require Enterprise Bot Management. On standard plans, querying these fields in the WAF Expression Builder returns a parsing error (unknown identifier).

To solve this without upgrading contracts, we look for HTTP/2 Client Hints anomalies in Layer 7 metadata.

3. Protocol Anomaly Detection: Leveraging sec-ch-ua

Modern Chromium-based browsers (Chrome, Edge, Brave, Opera) send modern W3C standard headers called User-Agent Client Hints on every HTTP/HTTPS request:

User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) ... Chrome/122.0.0.0
Sec-CH-UA: "Chromium";v="122", "Not(A:Brand";v="24", "Google Chrome";v="122"
Sec-CH-UA-Mobile: ?0
Sec-CH-UA-Platform: "Windows"

When an attacker or automated script uses curl -A "Mozilla/5.0...", it only modifies the legacy User-Agent string. It does not automatically reconstruct the underlying Client Hints header structure unless explicitly crafted.

This creates a detectable protocol anomaly: a request claiming to be Chrome while omitting Chrome's mandatory Client Hint headers.

4. Edge Rule Implementation

To catch spoofed automation at the global edge, we construct a Cloudflare Custom WAF Rule focused on header correlation:

  • Rule Name: [SecOps IR] Spoofed Chrome UA - Missing Client Hints
  • Action: Block (HTTP 403)
  • Expression:
(http.user_agent contains "Chrome") and not (any(http.request.headers.names[*] eq "sec-ch-ua"))

Expression Logic Breakdown

  1. http.user_agent contains "Chrome": The client claims to be a Chrome browser in the legacy header.
  2. not (any(http.request.headers.names[*] eq "sec-ch-ua")): The request headers lack the mandatory sec-ch-ua Client Hint string.
  3. Verdict: Anomaly confirmed. The client is spoofing its identity. Block immediately at the edge.

5. Incident Response & Telemetry Validation

To validate the rule, we execute the exact same spoofed curl command against the protected domain:

curl.exe -A "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36" -I https://experiement.xyz

Mitigation Output

HTTP/1.1 403 Forbidden
Date: Wed, 30 Sep 2026 12:21:16 GMT
Content-Type: text/html; charset=UTF-8
Connection: keep-alive
Server: cloudflare
CF-RAY: a4332fb7ad42f55c-LIS

Telemetry Analysis

  • Mitigation Response: HTTP 403 Forbidden was returned instantaneously from Cloudflare's Lisbon PoP (-LIS).
  • Zero False Positives: Legitimate browser traffic from Chrome, Edge, or Brave passes through unaffected, as those browsers naturally include sec-ch-ua.
  • Zero Origin Load: The malicious request was dropped entirely at the edge network before consuming any backend compute or bandwidth.

SecOps Key Takeaways

  1. Static User-Agent filtering is ineffective: Any attacker can bypass basic string matching in seconds.
  2. Correlate headers when TLS fingerprinting is unavailable: When Enterprise-level TLS inspection (JA4) isn't available on standard plan tiers, cross-referencing HTTP/2 Client Hints (sec-ch-ua) provides near-identical mitigation accuracy against automated spoofing.
  3. Shift response to the Edge: Dropping spoofed reconnaissance traffic at the nearest Point of Presence (PoP) reduces origin attack surface and keeps log noise clean.

Read more