Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ This keeps showing up in recent advisories because the primitive is very powerfu
- some implementations let you control the **method**, **headers**, and even the **body**
- the webhook worker is commonly allowed to reach **RFC1918**, **localhost**, and **link-local metadata** unless explicit SSRF protections exist

Recent examples include webhook SSRF issues in [**Grafana OnCall**](https://grafana.com/security/security-advisories/cve-2024-5526/), [**Gogs**](https://github.com/gogs/gogs/security/advisories/GHSA-w689-557m-2cvq), [**Soft Serve**](https://github.com/charmbracelet/soft-serve/security/advisories/GHSA-vwq2-jx9q-9h9f), and [**Firecrawl**](https://github.com/firecrawl/firecrawl/security/advisories/GHSA-p2wg-prhf-jx79).
Recent examples include webhook SSRF issues in [**Grafana OnCall**](https://grafana.com/security/security-advisories/cve-2024-5526/), [**Gogs**](https://github.com/gogs/gogs/security/advisories/GHSA-w689-557m-2cvq), [**Soft Serve**](https://github.com/charmbracelet/soft-serve/security/advisories/GHSA-vwq2-jx9q-9h9f), and [**Firecrawl**](https://github.com/firecrawl/firecrawl/security/advisories/GHSA-p2wg-prhf-jx79).<sup>[[1]](#references)[[2]](#references)[[3]](#references)[[4]](#references)</sup>

Useful first probes:

Expand Down Expand Up @@ -76,10 +76,10 @@ A lot of modern applications fetch remote content on behalf of the user without
- **feed readers**, **scrapers**, **crawler jobs**, **markdown previewers**
- **OCR**, **AI image-generation**, and other model pipelines that first fetch a URL and then pass the bytes downstream

A recent high-value example is **Next.js**:<sup>[[2]](#references)</sup>
A recent high-value example is **Next.js**:<sup>[[5]](#references)</sup>

- the **`_next/image`** endpoint becomes a blind SSRF gadget when `remotePatterns` are too broad or when an allowed domain has an **open redirect**
- **Server Actions** had a 2024 SSRF bug where a crafted request plus a server-side redirect could be turned into a **full-read SSRF** (fixed in [**Next.js 14.1.1**](https://github.com/vercel/next.js/security/advisories/GHSA-fr5h-rqp8-mj6g))
- **Server Actions** had a 2024 SSRF bug where a crafted request plus a server-side redirect could be turned into a **full-read SSRF** (fixed in [**Next.js 14.1.1**](https://github.com/vercel/next.js/security/advisories/GHSA-fr5h-rqp8-mj6g))<sup>[[6]](#references)</sup>

Examples:

Expand All @@ -97,7 +97,7 @@ When auditing these features, look for places where the platform:

### AI/OCR/media pipelines: verify **who** really fetches the URL

A URL parameter that eventually influences OCR or image generation is **not automatically a useful SSRF against the target environment**. First map the fetch origin:
A URL parameter that eventually influences OCR or image generation is **not automatically a useful SSRF against the target environment**. First map the fetch origin:<sup>[[7]](#references)</sup>

- **target backend fetches it directly** --> real SSRF against that environment
- **third-party service fetches it** (OCR provider, cloud Vision API, external crawler) --> the request originates from that provider, so you usually **can't reach the target's localhost, RFC1918 space, or metadata endpoints**
Expand All @@ -112,7 +112,7 @@ Quick triage workflow:

### Turning blind SSRF into readable output through downstream processors

If the server fetches the URL but does **not** return the body, inspect every field that controls how the fetched bytes are handled afterwards:
If the server fetches the URL but does **not** return the body, inspect every field that controls how the fetched bytes are handled afterwards:<sup>[[7]](#references)</sup>

- `mime_type`, `content_type`, `file_type`, `parser`, `mode`, `format`
- prompt / attachment metadata sent to an OCR, LLM, preview, or image-generation pipeline
Expand All @@ -125,7 +125,7 @@ A common upgrade path is:
3. force the downstream processor to treat the response as **text** (for example `mime_type=text/plain`)
4. look for the fetched response rendered inside the final artifact (generated image, OCR text, preview, moderation output, LLM response, PDF, etc.)

This turns a blind callback into **response exfiltration** without ever receiving the raw HTTP body directly. In modern AI features, the vulnerable pattern is often: **fetch attacker URL -> base64/attach response -> send it to the model together with attacker-controlled type metadata -> render model output back to the user**.<sup>[[3]](#references)</sup>
This turns a blind callback into **response exfiltration** without ever receiving the raw HTTP body directly. In modern AI features, the vulnerable pattern is often: **fetch attacker URL -> base64/attach response -> send it to the model together with attacker-controlled type metadata -> render model output back to the user**.

Useful proof targets once you suspect this pattern:

Expand All @@ -143,7 +143,7 @@ If you can only see error strings, they still help a lot: DNS failures, TLS vali

When the primitive is blind, try to bounce it through **internal software that performs another outbound request** to your OAST domain. This both **proves reachability** and often **fingerprints the internal platform**.

High-signal candidates taken from the Assetnote blind SSRF chains research:<sup>[[1]](#references)</sup>
High-signal candidates taken from the Assetnote blind SSRF chains research:<sup>[[8]](#references)</sup>

<details>
<summary>Useful blind SSRF canaries</summary>
Expand Down Expand Up @@ -180,7 +180,7 @@ Other evergreen internal targets worth probing from a SSRF sink are:
- **Prometheus / exporters / internal observability stacks**
- **Go `pprof`**: `/debug/pprof/`, `/debug/pprof/cmdline`, `/debug/pprof/goroutine?debug=1`, `/debug/pprof/heap`

This page is intentionally keeping the list short. For a much larger chain catalog, check the original Blind SSRF Chains research linked below.
This page is intentionally keeping the list short. For a much larger chain catalog, check the original Blind SSRF Chains research linked below.<sup>[[8]](#references)</sup>

## Practical workflow

Expand All @@ -202,7 +202,13 @@ A blind SSRF with only **DNS callbacks** can still be enough to:

## References

- [1] [Assetnote - A Glossary of Blind SSRF Chains](https://blog.assetnote.io/2021/01/13/blind-ssrf-chains/)
- [2] [Assetnote - Digging for SSRF in NextJS apps](https://www.assetnote.io/resources/research/digging-for-ssrf-in-nextjs-apps/)
- [3] [Bishop Fox - AI Finds Vulnerabilities. Security Experts Find Impact.](https://bishopfox.com/blog/ai-finds-vulnerabilities-security-experts-find-impact)
- [1] [Grafana OnCall webhook SSRF advisory (CVE-2024-5526)](https://grafana.com/security/security-advisories/cve-2024-5526/)
- [2] [Gogs webhook SSRF advisory (GHSA-w689-557m-2cvq)](https://github.com/gogs/gogs/security/advisories/GHSA-w689-557m-2cvq)
- [3] [Soft Serve webhook SSRF advisory (GHSA-vwq2-jx9q-9h9f)](https://github.com/charmbracelet/soft-serve/security/advisories/GHSA-vwq2-jx9q-9h9f)
- [4] [Firecrawl webhook SSRF advisory (GHSA-p2wg-prhf-jx79)](https://github.com/firecrawl/firecrawl/security/advisories/GHSA-p2wg-prhf-jx79)
- [5] [Assetnote - Digging for SSRF in NextJS apps](https://www.assetnote.io/resources/research/digging-for-ssrf-in-nextjs-apps/)
- [6] [Next.js Server Actions SSRF advisory (GHSA-fr5h-rqp8-mj6g)](https://github.com/vercel/next.js/security/advisories/GHSA-fr5h-rqp8-mj6g)
- [7] [Bishop Fox - AI Finds Vulnerabilities. Security Experts Find Impact.](https://bishopfox.com/blog/ai-finds-vulnerabilities-security-experts-find-impact)
- [8] [Assetnote - A Glossary of Blind SSRF Chains](https://blog.assetnote.io/2021/01/13/blind-ssrf-chains/)

{{#include ../../banners/hacktricks-training.md}}
Loading