Stackbook Logo
security-complianceestablished · medium operational burden

SSRF and Injection-Safe Design

Also known as: input-sanitization-boundary, egress-allow-listing, parameterized-queries

Intent

Design request handling so untrusted input can neither choose where the server connects nor change the meaning of a command or query.

Problem

Features such as webhooks, URL previews and imports let users supply URLs, and string-built SQL or shell commands let input become code. Attackers use these to reach cloud metadata endpoints, internal services, or the database itself.

Forces

  • •Features legitimately need to fetch user-specified URLs
  • •Internal networks and metadata services are implicitly trusted
  • •Blacklists of bad inputs are always incomplete
  • •Developers build queries and commands by concatenation for convenience

Solution

Overview

Server-side request forgery turns your server into a proxy into networks the attacker cannot reach. Injection turns data into instructions. Both stem from letting untrusted input cross a trust boundary unchecked, and both are fixed by structure rather than filtering.

Make the safe path the easy one by providing a single shared HTTP client for user-supplied URLs and a data access layer that only accepts parameters. Add static analysis rules that flag raw string queries and unvetted outbound requests, and include these vulnerability classes in routine penetration tests.

How it works

fetch(userUrl):
  u = parse(userUrl); require scheme == https, port in 443
  require host in allowList OR public-only
  ip = resolve(u.host)
  reject if ip in 10/8, 172.16/12, 192.168/16, 127/8, 169.254/16, ::1, fc00::/7
  connect to ip with Host header = u.host   # no second DNS lookup
  follow redirects manually, repeat checks, max 3 hops
  limit size and time; run in sandbox with egress proxy

query: db.execute("SELECT * FROM t WHERE id = ?", [id])   # never concatenate

Pitfalls

  • Checking the hostname string but not the resolved address.
  • Allowing redirects or non-HTTP schemes such as file or gopher.
  • Returning full upstream responses and error text, which helps attackers probe.
  • Using string escaping instead of parameterization.
  • Leaving cloud metadata reachable with IMDSv1.
  • Validating once at the edge while internal callers bypass it.

Key takeaways

  • Parameterize queries and avoid shell strings.
  • Validate the resolved IP, pin it, and re-check on redirects.
  • Isolate fetchers and deny egress by default.
  • Prefer allow-lists over blacklists.

✓ When to Use

  • •Webhooks, link previews, file import by URL
  • •Any code building queries, commands or templates from input
  • •Services running in clouds with metadata endpoints

✗ When Not to Use

  • •Services with no user-influenced outbound calls (still parameterize queries)
  • •As a replacement for authorization
  • •Relying on regex blacklists alone

Pros

  • +Eliminates whole vulnerability classes by construction
  • +Network egress limits cap damage from any miss
  • +Easy to enforce with linters and shared libraries

Cons

  • −Allow-lists need maintenance
  • −Isolated fetch workers add infrastructure
  • −DNS rebinding handling is subtle

Cost Profile

Infrastructure

Low to medium — egress proxy

Operational

Low to medium

Cognitive

Medium

Failure Modes

  • DNS rebinding passes validation then connects to an internal address

  • Redirect to an internal URL after a safe first hop

  • One raw query concatenation reopens SQL injection

Real-World Examples

Alternatives

    Related Patterns

      Competency Domains

      security compliancerequirements constraints