Lab 04 — Go Webhook Verification and Egress Gateway

Language: Go | Tools: go test | Difficulty: 4/5

Pairs with the Phase 02 WARMUP Chapter 11 (SSRF as routing + identity) and the HITCHHIKERS-GUIDE ("SSRF Hardening Procedure").

Why This Lab Exists (Purpose & Goal)

Webhooks sit at a uniquely dangerous intersection: a service that receives signed messages from a third party and makes outbound requests on attacker-influenceable input. Get the inbound side wrong and anyone can forge events; get the outbound side wrong and you have built a Server-Side Request Forgery (SSRF) primitive that can reach your cloud metadata endpoint and steal credentials. SSRF was the root cause of the Capital One breach (over 100 million records). The goal of this lab is to build both halves correctly: verify signatures over the exact bytes, and constrain outbound fetches so they can never reach internal infrastructure.

The Concept, In the Weeds

Inbound — sign the bytes, not the meaning. The HMAC signature must be computed over the exact raw body, not over parsed-then-re-serialized JSON. If you verify a re-serialized form, two byte streams that parse to the "same" object can have different signatures — and an attacker exploits the gap. Freshness (timestamp window) and nonce replay protection stop a captured-and-replayed valid message; a body-size cap stops resource abuse.

Outbound — SSRF is routing plus identity. When your server fetches an attacker-chosen URL, the request carries your server's network position and credentials. The naive defense — a string allowlist on the hostname — fails around URL-parser quirks, redirects, DNS rebinding (the name resolves to a safe IP during the check and an internal IP at connect time), alternate IP encodings, and proxies. The robust defense is a pipeline:

parse the URL once → restrict scheme/port (HTTPS only) → resolve via a controlled resolver
  → validate the RESOLVED IP (deny loopback, RFC1918, link-local, 169.254.169.254 metadata)
  → re-validate on EVERY redirect hop (pin the resolved address to defeat rebinding)
  → route through a constrained egress → attach NO ambient credentials

The key insight you must carry: validate the address you connect to, not the string the user typed.

Why This Matters for Protecting the Company

SSRF is consistently a critical finding because, in a cloud environment, reaching 169.254.169.254 hands the attacker the workload's IAM credentials — and from there, the cloud account. Any feature that fetches a URL on the user's behalf (webhooks, link previews, PDF/HTML imports, avatar-by-URL, integrations) is a candidate. When you can build and review an egress gateway that validates the resolved address on every hop and refuses internal ranges, you remove one of the most damaging attack classes from every such feature. The inbound HMAC discipline likewise protects every integration that trusts signed callbacks.

Run

go test ./solution
go test ./lab       # after implementing the TODOs

Attack / Failure Cases You Must Handle

Body changed after signing; signature computed over re-serialized JSON; stale timestamp or repeated nonce; oversized body; callback to loopback, RFC1918, link-local, the metadata service, a userinfo URL, non-HTTPS, or an unapproved host; and a redirect that must be re-validated by the HTTP client.

Validation — What You Should Be Able to Do Now

  • Explain why HMAC must cover the raw body and what breaks if you verify re-serialized JSON.
  • Build the SSRF-defense pipeline from memory and explain why a hostname allowlist is insufficient (parsing, redirects, DNS rebinding, alternate encodings).
  • Articulate why validating the resolved IP on every redirect hop (and pinning it) is the control that actually works.
  • Explain the cloud stakes: why metadata-endpoint access via SSRF is account-level compromise.

The Broader Perspective

This lab teaches the most important modern network-security idea for cloud-era services: the danger is not what the user named, but where the server actually connects — carrying the server's identity. That reframing — SSRF as the server's network position and credentials being borrowed by untrusted input — reappears as a first-class concern in sandbox egress control (Phase 06), in cloud network segmentation and metadata protection (Phase 07), and in AI-agent tool egress (Phase 11, the exfiltration leg of the lethal trifecta). Outbound traffic is an attack surface, and constraining it is as important as constraining inbound.

Interview Angle

  • "How do you defend against SSRF in a service that fetches user URLs?" — Parse once; allowlist scheme/port; resolve via a controlled resolver and validate the resolved IP against a deny-list (RFC1918, link-local, metadata); re-validate every redirect and pin the address (DNS rebinding); constrained egress; no ambient credentials. Validate the address you connect to, not the string.
  • "Why sign the raw body?" — Re-serialization changes bytes; an attacker exploits the difference between what was signed and what is processed.

Extension (Stretch)

Add the HTTP client integration with redirect revalidation, bounded workers, context cancellation, TLS policy, DNS pinning or a controlled proxy, and structured audit logs.

References

  • Phase 02 WARMUP Chapter 11; OWASP SSRF Cheat Sheet; the Capital One SSRF post-mortem.
  • Phase 06 (egress control), Phase 07 (cloud metadata protection).