#supply-chain#security#web

SSRF Explained Through Real-World Mistakes

· 3 min read

For a long time I treated SSRF as something to worry about later. Then a small change to our Burp Suite setup turned into a week of debugging, and "later" arrived all at once.

The first symptom was subtle. Nothing failed outright, but SSRF kept drifting in the wrong direction, and every fix seemed to make the next one harder.

The problem

Most of the complexity was accidental. Over the years we'd layered three different approaches to SSRF on top of each other, and each one made sense at the time.

We had good intentions. We even had a document describing how SSRF should work. The trouble was that the document and the code had quietly gone their separate ways.

Trying something different

Rather than a big-bang rewrite, we migrated one module at a time over about 6 weeks, keeping both paths alive behind a flag.

The core of it looks like this:

Content-Security-Policy: default-src 'self';
  script-src 'self' 'nonce-r4nd0m';
  style-src 'self';
  img-src 'self' data:;
  frame-ancestors 'none';
  base-uri 'self'

It's tempting to generalize this into a library. Resist that urge until you've needed it in at least three places.

A few things that helped along the way:

  • Measure before and after, even if it's just a rough number in a spreadsheet.
  • Keep the old path around until the new one has survived a real incident.
  • Agree on what "done" means before the first pull request.

Caveats

The biggest cost was social, not technical. Changing how people think about SSRF takes much longer than changing the code.

There are cases where this falls apart. If your team is very small or your traffic is very spiky, the extra moving parts may not pay for themselves.

Closing thoughts

If you take one thing away from this, let it be this: SSRF is a design decision, not a cleanup task. Make it early and make it on purpose.

KL
Kenji Lowe
Security engineer in Boston. Writing about application security.