SSRFmap Cheat Sheet: Every Module and Flag I Actually Use
A field-tested SSRFmap reference: target capture, the real module list (readfiles, portscan, redis, fastcgi, mysql, smtp, axfr, aws, gce, alibaba, digitalocean, github, zabbix, postgres, docker, socksproxy, smbhash, tomcat, memcache, networkscan, custom), handler setup, cloud metadata workflows, and where Burp Repeater is still the better tool.
SSRFmap is a small Python tool that turns a captured request file plus a parameter name into a chain of SSRF exploit modules. It does the parts that are boring to hand-roll: port scanning the internal network through the vulnerable parameter, hitting Redis with gopher payloads, pulling files via the FastCGI socket, scraping cloud metadata. This is the field reference for the flags and modules I actually reach for, grouped by task.
The CLI surface is small and the flag set is fixed at -h, -r, -p, -m, -l, -v, --lhost, --lport, --uagent, --ssl, --proxy, --level, --rfiles. There is no --target, no --ports, no --handler, no --file. Cloud metadata and arbitrary-byte gopher payloads are written as custom modules.
Every module and flag organised by task. Copy and adapt.
Target and parameter (the entire CLI)
-r request.txtCaptured HTTP request file. Method, headers, cookies, body, all preserved. The only required input.
-p urlParameter name to inject into. Must exist somewhere in the request (query, body, header, cookie). SSRFmap substitutes its payloads in place of that parameter's value.
-m readfilesModule to run. Single module name or comma-separated list. See the module table below for the full set.
-m readfiles,portscan,redisChain multiple modules in one run. Each module reuses the same request and parameter.
-l 4242Start a handler on the given port for a reverse shell. This is a positional flag with an argument (not a boolean `--handler` switch).
--lhost 10.0.2.15LHOST: the address the target will reach back to (or the IP to target inside the network, depending on the module). LAN IP for local labs, public IP or tunnel endpoint for real targets.
--lport 4444LPORT for reverse shell, or the port to target inside the network (module-dependent).
--level 1Test depth. Accepts 1-5, default 1. Higher levels enable more obfuscation variants and more payload permutations, at the cost of speed.
-vVerbose. Prints every request SSRFmap sends and the raw response. Use this constantly when debugging a module that is not firing.
--proxy http://127.0.0.1:8080Route through Burp or any HTTP proxy. Best way to see exactly what SSRFmap is sending and tweak by hand.
--sslUse HTTPS without verification for the outbound request.
--uagent 'Mozilla/5.0 ...'Override the User-Agent. The default contains 'ssrfmap' and is signatured by every commercial WAF.
--rfiles /tmp/paths.txtOverride the readfiles wordlist with your own paths. One path per line. Use for app-specific config (Rails secrets.yml, Django settings.py, .env).
Built-in modules (the real list)
readfilesRead local files on the target via file:// (and tries gopher://, dict://, ftp://). Walks a built-in wordlist of common paths (/etc/passwd, /etc/shadow, app config files). Override with --rfiles.
portscanScan internal ports through the SSRF. Port range is module-internal, not a top-level flag.
networkscanScan a range of internal hosts/ports through the SSRF. Use when portscan against a single host has confirmed the SSRF reaches the internal network.
redisSend arbitrary Redis commands via gopher://. Writes a cron entry or SSH key into Redis if it is unauthenticated. Set --lhost / --lport when the cron job should call back.
fastcgiTalk to a php-fpm FastCGI socket on the internal network via gopher://. Executes arbitrary PHP code in the FastCGI worker. Devastating against a misconfigured fpm bound to 0.0.0.0:9000.
mysqlSend MySQL protocol bytes through gopher://. Useful when an internal MySQL trusts localhost and accepts no-password root logins from the app server.
postgresSame idea against PostgreSQL: protocol bytes through gopher:// to an internal listener that trusts the app server's IP.
smtpSpeak SMTP through gopher:// to an internal mail relay. Send mail as the application, often bypassing SPF/DMARC because the relay trusts internal traffic.
memcacheHit an internal memcached over gopher://. Useful for cache poisoning when the app reads cached session/auth state.
axfrAttempt a DNS zone transfer against an internal nameserver via the SSRF parameter. When the internal resolver allows AXFR you get the entire internal zone.
githubHit GitHub Enterprise / Actions metadata endpoints reachable from the SSRF. Pulls tokens that often leak in misconfigured runners. Verify against your target's GHES version before assuming the endpoints still respond.
zabbixHit an internal Zabbix server via the SSRF. Pulls server info and (in older versions) credentials.
dockerTalk to a Docker daemon socket exposed on tcp://internal:2375 with no auth. Lists containers, starts new ones, escalates to host.
tomcatAuthenticated and unauthenticated probes against an internal Tomcat manager. Default-creds checks plus version fingerprint.
smbhashForce the target to authenticate to an attacker-controlled SMB share so the NTLMv2 hash lands in your responder/impacket listener.
socksproxyPivot through the SSRF as a SOCKS proxy. Heavy and rarely worth it; use only when the chain genuinely needs proxying.
awsAWS metadata module. Reaches 169.254.169.254 and pulls IAM role names plus the credentials JSON. IMDSv1 only by default; IMDSv2 requires a PUT and a token header most SSRF primitives do not allow.
gceGoogle Compute Engine metadata module. Reaches metadata.google.internal/computeMetadata/v1/. Requires the Metadata-Flavor: Google header, which the SSRF must let you set; many do not.
digitaloceanDigitalOcean metadata module. Reaches 169.254.169.254/metadata/v1/. No auth header required, which is why DO SSRFs are the cleanest of the lot.
customRun all user-written modules in data/modules/custom/. Drop a Python file there to extend the tool. (Module name is singular `custom`, not `customs`.)
Cloud metadata recipes (use the dedicated modules)
AWS (IMDSv1)`-m aws` reaches 169.254.169.254/latest/meta-data/, pulls the IAM role name, then the credentials JSON. IMDSv1 has no token requirement; works against any EC2 where IMDSv2 was not enforced.
AWS (IMDSv2)IMDSv2 requires a PUT to /latest/api/token with X-aws-ec2-metadata-token-ttl-seconds. The aws module cannot issue that PUT through a typical SSRF; if IMDSv1 is disabled on the instance, fall back to a custom module that handles the token dance or move to a different chain.
GCP`-m gce` reaches metadata.google.internal and reads /instance/service-accounts/default/token for an OAuth token. Requires Metadata-Flavor: Google on the outbound request; if the SSRF does not let you set headers, write a custom module that injects the header before do_request().
AzureNo dedicated `-m azure` module in upstream. Azure IMDS requires Metadata: true header at 169.254.169.254/metadata/instance?api-version=2021-02-01. Write a custom module or develop the chain in Burp Repeater.
DigitalOcean`-m digitalocean` reaches 169.254.169.254/metadata/v1/. No auth header. The cleanest of the bunch.
Alibaba`-m alibaba` reaches 100.100.100.200/latest/meta-data/. No auth header, separate IP from the other providers.
Kubernetes nodeFrom a pod with a clean SSRF, http://169.254.169.254/ may still hit the cloud IMDS. The projected serviceaccount token at /var/run/secrets/kubernetes.io/serviceaccount/token comes out via the readfiles module.
Reachability and handler setup
Local LAN target--lhost 192.168.1.50 (your LAN IP) and --lport 4444. Target must route to your machine. Most lab setups (DVWA, juice-shop, training boxes on the same network) work like this.
Remote target, tunnel backRun ngrok or cloudflared tunneling 4444 to a public hostname, then --lhost=your-tunnel.example --lport=443. The target hits the tunnel; the tunnel forwards to your local handler.
Reverse-shell handlerPass `-l 4242` (positional argument, port number) and SSRFmap binds that port for the inbound shell. Skip it if you have a separate nc / metasploit listener already running.
Blind SSRF confirmationThere is no dedicated `dns` module. The simplest blind oracle is a hand-crafted SSRF in Burp pointing at your interactsh subdomain, or an axfr probe against an attacker-controlled NS. Confirm reachability before running heavier modules.
Check firstAlways send a manual probe (an http:// request to your collaborator) before running heavier modules. Saves an hour of debugging a payload that never reaches you.
Custom modules
Where they livedata/modules/custom/ in the cloned repo. Drop a Python file there; pick it up with `-m custom`.
Module shapeA class with a name attribute and an exploit(self, requester, args) method. requester is a wrapper around the captured request; call requester.do_request(url) and inspect the response.
When to write oneCloud providers that need a custom header SSRFmap does not inject (Azure Metadata: true, GCP variants the gce module does not cover), proprietary protocols over gopher://, header-injection via CRLF, and any chained workflow where module A's output feeds module B.
Quick stubCopy data/modules/readfiles.py as a template, swap the URL list and parsing, save under custom/ with a distinct class name. Test with `-m custom -v`.
Output and debugging
-vVerbose. Every request and response printed. First flag to add when something is not working.
--proxy http://127.0.0.1:8080Send all traffic through Burp. Inspect, repeat, modify. Best debugging tool SSRFmap has.
stdout onlySSRFmap does not write a structured report. Pipe to `tee output.log` if you want a saved transcript. Module results print inline as they fire.
Exit codes0 on completion, non-zero on argparse / file-load failures. A module finding nothing is still exit 0; do not script on exit code for success / failure of the actual exploit.
SSRFmap vs Burp Repeater (when to use which)
SSRFmap winsPort scanning a /24 of internal addresses through one parameter. Walking 200+ file paths with readfiles. Sending a gopher:// payload to Redis or FastCGI where the byte-level packet is annoying to hand-craft.
Burp Repeater winsSingle-shot probes against one URL. Anything requiring a custom header on the outbound request (Metadata-Flavor, X-aws-ec2-metadata-token, Azure Metadata: true) that the SSRF lets you set via CRLF. Tweaking payload encoding by hand.
Both togetherSSRFmap with --proxy http://127.0.0.1:8080 sends every request through Burp. You get SSRFmap's payload library and Burp's editing surface on the same traffic. This is the configuration I use 80% of the time.
Skip SSRFmap whenThe SSRF needs a request shape SSRFmap cannot produce (unusual method, custom content-type, multipart with binary parts in specific places). Burp Repeater plus the PayloadsAllTheThings SSRF wordlists is faster.
Target and parameter (the entire CLI)
-r request.txtCaptured HTTP request file. Method, headers, cookies, body, all preserved. The only required input.
-p urlParameter name to inject into. Must exist somewhere in the request (query, body, header, cookie). SSRFmap substitutes its payloads in place of that parameter's value.
-m readfilesModule to run. Single module name or comma-separated list. See the module table below for the full set.
-m readfiles,portscan,redisChain multiple modules in one run. Each module reuses the same request and parameter.
-l 4242Start a handler on the given port for a reverse shell. This is a positional flag with an argument (not a boolean `--handler` switch).
--lhost 10.0.2.15LHOST: the address the target will reach back to (or the IP to target inside the network, depending on the module). LAN IP for local labs, public IP or tunnel endpoint for real targets.
--lport 4444LPORT for reverse shell, or the port to target inside the network (module-dependent).
--level 1Test depth. Accepts 1-5, default 1. Higher levels enable more obfuscation variants and more payload permutations, at the cost of speed.
-vVerbose. Prints every request SSRFmap sends and the raw response. Use this constantly when debugging a module that is not firing.
--proxy http://127.0.0.1:8080Route through Burp or any HTTP proxy. Best way to see exactly what SSRFmap is sending and tweak by hand.
--sslUse HTTPS without verification for the outbound request.
--uagent 'Mozilla/5.0 ...'Override the User-Agent. The default contains 'ssrfmap' and is signatured by every commercial WAF.
--rfiles /tmp/paths.txtOverride the readfiles wordlist with your own paths. One path per line. Use for app-specific config (Rails secrets.yml, Django settings.py, .env).
Cloud metadata recipes (use the dedicated modules)
AWS (IMDSv1)`-m aws` reaches 169.254.169.254/latest/meta-data/, pulls the IAM role name, then the credentials JSON. IMDSv1 has no token requirement; works against any EC2 where IMDSv2 was not enforced.
AWS (IMDSv2)IMDSv2 requires a PUT to /latest/api/token with X-aws-ec2-metadata-token-ttl-seconds. The aws module cannot issue that PUT through a typical SSRF; if IMDSv1 is disabled on the instance, fall back to a custom module that handles the token dance or move to a different chain.
GCP`-m gce` reaches metadata.google.internal and reads /instance/service-accounts/default/token for an OAuth token. Requires Metadata-Flavor: Google on the outbound request; if the SSRF does not let you set headers, write a custom module that injects the header before do_request().
AzureNo dedicated `-m azure` module in upstream. Azure IMDS requires Metadata: true header at 169.254.169.254/metadata/instance?api-version=2021-02-01. Write a custom module or develop the chain in Burp Repeater.
DigitalOcean`-m digitalocean` reaches 169.254.169.254/metadata/v1/. No auth header. The cleanest of the bunch.
Alibaba`-m alibaba` reaches 100.100.100.200/latest/meta-data/. No auth header, separate IP from the other providers.
Kubernetes nodeFrom a pod with a clean SSRF, http://169.254.169.254/ may still hit the cloud IMDS. The projected serviceaccount token at /var/run/secrets/kubernetes.io/serviceaccount/token comes out via the readfiles module.
Custom modules
Where they livedata/modules/custom/ in the cloned repo. Drop a Python file there; pick it up with `-m custom`.
Module shapeA class with a name attribute and an exploit(self, requester, args) method. requester is a wrapper around the captured request; call requester.do_request(url) and inspect the response.
When to write oneCloud providers that need a custom header SSRFmap does not inject (Azure Metadata: true, GCP variants the gce module does not cover), proprietary protocols over gopher://, header-injection via CRLF, and any chained workflow where module A's output feeds module B.
Quick stubCopy data/modules/readfiles.py as a template, swap the URL list and parsing, save under custom/ with a distinct class name. Test with `-m custom -v`.
Output and debugging
-vVerbose. Every request and response printed. First flag to add when something is not working.
--proxy http://127.0.0.1:8080Send all traffic through Burp. Inspect, repeat, modify. Best debugging tool SSRFmap has.
stdout onlySSRFmap does not write a structured report. Pipe to `tee output.log` if you want a saved transcript. Module results print inline as they fire.
Exit codes0 on completion, non-zero on argparse / file-load failures. A module finding nothing is still exit 0; do not script on exit code for success / failure of the actual exploit.
Built-in modules (the real list)
readfilesRead local files on the target via file:// (and tries gopher://, dict://, ftp://). Walks a built-in wordlist of common paths (/etc/passwd, /etc/shadow, app config files). Override with --rfiles.
portscanScan internal ports through the SSRF. Port range is module-internal, not a top-level flag.
networkscanScan a range of internal hosts/ports through the SSRF. Use when portscan against a single host has confirmed the SSRF reaches the internal network.
redisSend arbitrary Redis commands via gopher://. Writes a cron entry or SSH key into Redis if it is unauthenticated. Set --lhost / --lport when the cron job should call back.
fastcgiTalk to a php-fpm FastCGI socket on the internal network via gopher://. Executes arbitrary PHP code in the FastCGI worker. Devastating against a misconfigured fpm bound to 0.0.0.0:9000.
mysqlSend MySQL protocol bytes through gopher://. Useful when an internal MySQL trusts localhost and accepts no-password root logins from the app server.
postgresSame idea against PostgreSQL: protocol bytes through gopher:// to an internal listener that trusts the app server's IP.
smtpSpeak SMTP through gopher:// to an internal mail relay. Send mail as the application, often bypassing SPF/DMARC because the relay trusts internal traffic.
memcacheHit an internal memcached over gopher://. Useful for cache poisoning when the app reads cached session/auth state.
axfrAttempt a DNS zone transfer against an internal nameserver via the SSRF parameter. When the internal resolver allows AXFR you get the entire internal zone.
githubHit GitHub Enterprise / Actions metadata endpoints reachable from the SSRF. Pulls tokens that often leak in misconfigured runners. Verify against your target's GHES version before assuming the endpoints still respond.
zabbixHit an internal Zabbix server via the SSRF. Pulls server info and (in older versions) credentials.
dockerTalk to a Docker daemon socket exposed on tcp://internal:2375 with no auth. Lists containers, starts new ones, escalates to host.
tomcatAuthenticated and unauthenticated probes against an internal Tomcat manager. Default-creds checks plus version fingerprint.
smbhashForce the target to authenticate to an attacker-controlled SMB share so the NTLMv2 hash lands in your responder/impacket listener.
socksproxyPivot through the SSRF as a SOCKS proxy. Heavy and rarely worth it; use only when the chain genuinely needs proxying.
awsAWS metadata module. Reaches 169.254.169.254 and pulls IAM role names plus the credentials JSON. IMDSv1 only by default; IMDSv2 requires a PUT and a token header most SSRF primitives do not allow.
gceGoogle Compute Engine metadata module. Reaches metadata.google.internal/computeMetadata/v1/. Requires the Metadata-Flavor: Google header, which the SSRF must let you set; many do not.
digitaloceanDigitalOcean metadata module. Reaches 169.254.169.254/metadata/v1/. No auth header required, which is why DO SSRFs are the cleanest of the lot.
customRun all user-written modules in data/modules/custom/. Drop a Python file there to extend the tool. (Module name is singular `custom`, not `customs`.)
Reachability and handler setup
Local LAN target--lhost 192.168.1.50 (your LAN IP) and --lport 4444. Target must route to your machine. Most lab setups (DVWA, juice-shop, training boxes on the same network) work like this.
Remote target, tunnel backRun ngrok or cloudflared tunneling 4444 to a public hostname, then --lhost=your-tunnel.example --lport=443. The target hits the tunnel; the tunnel forwards to your local handler.
Reverse-shell handlerPass `-l 4242` (positional argument, port number) and SSRFmap binds that port for the inbound shell. Skip it if you have a separate nc / metasploit listener already running.
Blind SSRF confirmationThere is no dedicated `dns` module. The simplest blind oracle is a hand-crafted SSRF in Burp pointing at your interactsh subdomain, or an axfr probe against an attacker-controlled NS. Confirm reachability before running heavier modules.
Check firstAlways send a manual probe (an http:// request to your collaborator) before running heavier modules. Saves an hour of debugging a payload that never reaches you.
SSRFmap vs Burp Repeater (when to use which)
SSRFmap winsPort scanning a /24 of internal addresses through one parameter. Walking 200+ file paths with readfiles. Sending a gopher:// payload to Redis or FastCGI where the byte-level packet is annoying to hand-craft.
Burp Repeater winsSingle-shot probes against one URL. Anything requiring a custom header on the outbound request (Metadata-Flavor, X-aws-ec2-metadata-token, Azure Metadata: true) that the SSRF lets you set via CRLF. Tweaking payload encoding by hand.
Both togetherSSRFmap with --proxy http://127.0.0.1:8080 sends every request through Burp. You get SSRFmap's payload library and Burp's editing surface on the same traffic. This is the configuration I use 80% of the time.
Skip SSRFmap whenThe SSRF needs a request shape SSRFmap cannot produce (unusual method, custom content-type, multipart with binary parts in specific places). Burp Repeater plus the PayloadsAllTheThings SSRF wordlists is faster.
Target and parameter (the entire CLI)
-r request.txtCaptured HTTP request file. Method, headers, cookies, body, all preserved. The only required input.
-p urlParameter name to inject into. Must exist somewhere in the request (query, body, header, cookie). SSRFmap substitutes its payloads in place of that parameter's value.
-m readfilesModule to run. Single module name or comma-separated list. See the module table below for the full set.
-m readfiles,portscan,redisChain multiple modules in one run. Each module reuses the same request and parameter.
-l 4242Start a handler on the given port for a reverse shell. This is a positional flag with an argument (not a boolean `--handler` switch).
--lhost 10.0.2.15LHOST: the address the target will reach back to (or the IP to target inside the network, depending on the module). LAN IP for local labs, public IP or tunnel endpoint for real targets.
--lport 4444LPORT for reverse shell, or the port to target inside the network (module-dependent).
--level 1Test depth. Accepts 1-5, default 1. Higher levels enable more obfuscation variants and more payload permutations, at the cost of speed.
-vVerbose. Prints every request SSRFmap sends and the raw response. Use this constantly when debugging a module that is not firing.
--proxy http://127.0.0.1:8080Route through Burp or any HTTP proxy. Best way to see exactly what SSRFmap is sending and tweak by hand.
--sslUse HTTPS without verification for the outbound request.
--uagent 'Mozilla/5.0 ...'Override the User-Agent. The default contains 'ssrfmap' and is signatured by every commercial WAF.
--rfiles /tmp/paths.txtOverride the readfiles wordlist with your own paths. One path per line. Use for app-specific config (Rails secrets.yml, Django settings.py, .env).
Cloud metadata recipes (use the dedicated modules)
AWS (IMDSv1)`-m aws` reaches 169.254.169.254/latest/meta-data/, pulls the IAM role name, then the credentials JSON. IMDSv1 has no token requirement; works against any EC2 where IMDSv2 was not enforced.
AWS (IMDSv2)IMDSv2 requires a PUT to /latest/api/token with X-aws-ec2-metadata-token-ttl-seconds. The aws module cannot issue that PUT through a typical SSRF; if IMDSv1 is disabled on the instance, fall back to a custom module that handles the token dance or move to a different chain.
GCP`-m gce` reaches metadata.google.internal and reads /instance/service-accounts/default/token for an OAuth token. Requires Metadata-Flavor: Google on the outbound request; if the SSRF does not let you set headers, write a custom module that injects the header before do_request().
AzureNo dedicated `-m azure` module in upstream. Azure IMDS requires Metadata: true header at 169.254.169.254/metadata/instance?api-version=2021-02-01. Write a custom module or develop the chain in Burp Repeater.
DigitalOcean`-m digitalocean` reaches 169.254.169.254/metadata/v1/. No auth header. The cleanest of the bunch.
Alibaba`-m alibaba` reaches 100.100.100.200/latest/meta-data/. No auth header, separate IP from the other providers.
Kubernetes nodeFrom a pod with a clean SSRF, http://169.254.169.254/ may still hit the cloud IMDS. The projected serviceaccount token at /var/run/secrets/kubernetes.io/serviceaccount/token comes out via the readfiles module.
Custom modules
Where they livedata/modules/custom/ in the cloned repo. Drop a Python file there; pick it up with `-m custom`.
Module shapeA class with a name attribute and an exploit(self, requester, args) method. requester is a wrapper around the captured request; call requester.do_request(url) and inspect the response.
When to write oneCloud providers that need a custom header SSRFmap does not inject (Azure Metadata: true, GCP variants the gce module does not cover), proprietary protocols over gopher://, header-injection via CRLF, and any chained workflow where module A's output feeds module B.
Quick stubCopy data/modules/readfiles.py as a template, swap the URL list and parsing, save under custom/ with a distinct class name. Test with `-m custom -v`.
Output and debugging
-vVerbose. Every request and response printed. First flag to add when something is not working.
--proxy http://127.0.0.1:8080Send all traffic through Burp. Inspect, repeat, modify. Best debugging tool SSRFmap has.
stdout onlySSRFmap does not write a structured report. Pipe to `tee output.log` if you want a saved transcript. Module results print inline as they fire.
Exit codes0 on completion, non-zero on argparse / file-load failures. A module finding nothing is still exit 0; do not script on exit code for success / failure of the actual exploit.
Built-in modules (the real list)
readfilesRead local files on the target via file:// (and tries gopher://, dict://, ftp://). Walks a built-in wordlist of common paths (/etc/passwd, /etc/shadow, app config files). Override with --rfiles.
portscanScan internal ports through the SSRF. Port range is module-internal, not a top-level flag.
networkscanScan a range of internal hosts/ports through the SSRF. Use when portscan against a single host has confirmed the SSRF reaches the internal network.
redisSend arbitrary Redis commands via gopher://. Writes a cron entry or SSH key into Redis if it is unauthenticated. Set --lhost / --lport when the cron job should call back.
fastcgiTalk to a php-fpm FastCGI socket on the internal network via gopher://. Executes arbitrary PHP code in the FastCGI worker. Devastating against a misconfigured fpm bound to 0.0.0.0:9000.
mysqlSend MySQL protocol bytes through gopher://. Useful when an internal MySQL trusts localhost and accepts no-password root logins from the app server.
postgresSame idea against PostgreSQL: protocol bytes through gopher:// to an internal listener that trusts the app server's IP.
smtpSpeak SMTP through gopher:// to an internal mail relay. Send mail as the application, often bypassing SPF/DMARC because the relay trusts internal traffic.
memcacheHit an internal memcached over gopher://. Useful for cache poisoning when the app reads cached session/auth state.
axfrAttempt a DNS zone transfer against an internal nameserver via the SSRF parameter. When the internal resolver allows AXFR you get the entire internal zone.
githubHit GitHub Enterprise / Actions metadata endpoints reachable from the SSRF. Pulls tokens that often leak in misconfigured runners. Verify against your target's GHES version before assuming the endpoints still respond.
zabbixHit an internal Zabbix server via the SSRF. Pulls server info and (in older versions) credentials.
dockerTalk to a Docker daemon socket exposed on tcp://internal:2375 with no auth. Lists containers, starts new ones, escalates to host.
tomcatAuthenticated and unauthenticated probes against an internal Tomcat manager. Default-creds checks plus version fingerprint.
smbhashForce the target to authenticate to an attacker-controlled SMB share so the NTLMv2 hash lands in your responder/impacket listener.
socksproxyPivot through the SSRF as a SOCKS proxy. Heavy and rarely worth it; use only when the chain genuinely needs proxying.
awsAWS metadata module. Reaches 169.254.169.254 and pulls IAM role names plus the credentials JSON. IMDSv1 only by default; IMDSv2 requires a PUT and a token header most SSRF primitives do not allow.
gceGoogle Compute Engine metadata module. Reaches metadata.google.internal/computeMetadata/v1/. Requires the Metadata-Flavor: Google header, which the SSRF must let you set; many do not.
digitaloceanDigitalOcean metadata module. Reaches 169.254.169.254/metadata/v1/. No auth header required, which is why DO SSRFs are the cleanest of the lot.
customRun all user-written modules in data/modules/custom/. Drop a Python file there to extend the tool. (Module name is singular `custom`, not `customs`.)
Reachability and handler setup
Local LAN target--lhost 192.168.1.50 (your LAN IP) and --lport 4444. Target must route to your machine. Most lab setups (DVWA, juice-shop, training boxes on the same network) work like this.
Remote target, tunnel backRun ngrok or cloudflared tunneling 4444 to a public hostname, then --lhost=your-tunnel.example --lport=443. The target hits the tunnel; the tunnel forwards to your local handler.
Reverse-shell handlerPass `-l 4242` (positional argument, port number) and SSRFmap binds that port for the inbound shell. Skip it if you have a separate nc / metasploit listener already running.
Blind SSRF confirmationThere is no dedicated `dns` module. The simplest blind oracle is a hand-crafted SSRF in Burp pointing at your interactsh subdomain, or an axfr probe against an attacker-controlled NS. Confirm reachability before running heavier modules.
Check firstAlways send a manual probe (an http:// request to your collaborator) before running heavier modules. Saves an hour of debugging a payload that never reaches you.
SSRFmap vs Burp Repeater (when to use which)
SSRFmap winsPort scanning a /24 of internal addresses through one parameter. Walking 200+ file paths with readfiles. Sending a gopher:// payload to Redis or FastCGI where the byte-level packet is annoying to hand-craft.
Burp Repeater winsSingle-shot probes against one URL. Anything requiring a custom header on the outbound request (Metadata-Flavor, X-aws-ec2-metadata-token, Azure Metadata: true) that the SSRF lets you set via CRLF. Tweaking payload encoding by hand.
Both togetherSSRFmap with --proxy http://127.0.0.1:8080 sends every request through Burp. You get SSRFmap's payload library and Burp's editing surface on the same traffic. This is the configuration I use 80% of the time.
Skip SSRFmap whenThe SSRF needs a request shape SSRFmap cannot produce (unusual method, custom content-type, multipart with binary parts in specific places). Burp Repeater plus the PayloadsAllTheThings SSRF wordlists is faster.
SSRFmap takes the same kind of request.txt as sqlmap: raw HTTP, method line, headers, blank line, body. The parameter name passed with -p must appear somewhere in that request as a value SSRFmap can substitute.
code
POST /api/fetch HTTP/1.1
Host: target.example
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36
Content-Type: application/x-www-form-urlencoded
Content-Length: 38
Cookie: session=eyJhbGciOiJIUzI1NiJ9...
Connection: close
url=https://example.com/some-resource
Run python3 ssrfmap.py -r request.txt -p url -m readfiles and SSRFmap replaces the url parameter with file:///etc/passwd, file:///etc/shadow, and the rest of its wordlist. Same flow for query parameters, header values, and cookies; SSRFmap finds the parameter wherever it lives.
Capture the request the same way you would for sqlmap: DevTools Network tab, right-click, save the raw request. Or use Burp's "Copy to file" on a selected request.
Quick reachability check first. The cleanest blind oracle is a manual http:// SSRF in Burp pointing at your interactsh subdomain; if you would rather drive it from SSRFmap, use the axfr module to probe an attacker-controlled NS, or layer a custom module that hits your callback URL.
GCP requires Metadata-Flavor: Google. Azure requires Metadata: true. The bundled gce module sets the GCP header; Azure has no bundled module in upstream. Two practical workarounds for any case the built-in modules do not handle:
Write a custom module. Copy data/modules/readfiles.py to data/modules/custom/azure_metadata.py, hard-code the Azure URLs, and add the Metadata: true header when the module calls requester.do_request(). Run with -m custom.
Use Burp Repeater for these. When the SSRF lets you control the URL but not arbitrary headers on the outbound request, you usually cannot inject the metadata header anyway, and the metadata endpoint will refuse. The fix is on the SSRF side (find a path that lets you set headers via CRLF injection) rather than the tool side. Burp Repeater is where you actually develop that payload.
For completeness, parts of SSRFmap that exist but rarely earn their keep:
The github module against modern GitHub Enterprise releases. The metadata endpoints it targets have been hardened or moved; verify on the version in front of you before assuming it still works.
--level 3+ on a fast target. The extra obfuscation variants rarely flip a result that level 1 missed, and they multiply request count.
Running every module in one go (-m readfiles,portscan,redis,fastcgi,mysql,smtp,axfr,github,aws,gce,custom) without scoping. The noise drowns out the signal. Pick the two or three that match the internal services you suspect.
Every module above is dual use. The same fastcgi payload that pops a webshell on a CTF box is the one I run against my own lab containers. Use these only against systems you own or have explicit written authorisation to test. See the server-side request forgery explainer for the legal-framing notes.
Sources
Authoritative references this article was fact-checked against.
Tech architect and software engineer with 20+ years building software, Linux systems, and DevOps infrastructure, and lately working AI into the stack. Currently Chief Technology Officer at a healthcare tech startup, which is where most of these field notes come from.
A field-tested LFImap reference: target selection, traversal wordlists, PHP wrappers (filter/input/data/expect/file), command injection, RFI, log/proxy/cookie shaping, second-order requests, and the `PWN` placeholder. Grounded in the real argparse surface.
A field-tested sqlmap reference: target specification, request shaping, detection tuning, DBMS fingerprinting, enumeration, dumping, file system access, OS command execution, evasion, and tamper scripts. Grouped by what you are actually trying to do.