-
Notifications
You must be signed in to change notification settings - Fork 0
Module: SSRF
Module Name: ssrf
Requires Sink: HTTP
Server-Side Request Forgery (SSRF) is a vulnerability that allows attackers to induce the server to make HTTP requests to arbitrary destinations. This can be used to access internal services, cloud metadata endpoints, or interact with systems that trust the vulnerable server.
FlawFactory's SSRF module creates real SSRF vulnerabilities by making actual HTTP requests to URLs provided by the user.
Note: You may face SSL/TLS errors since self signed certificates can fail. Additionally, the HTTP sink doesn't verify certificates strictly, so some HTTPS sites may fail.
| Placement | Description | Example Request |
|---|---|---|
query_param |
URL query string | GET /fetch?url=http://example.com |
form_field |
POST form data |
POST /proxy with target=http://example.com
|
json_field |
JSON body field |
POST /api/fetch with {"url": "http://..."}
|
header |
HTTP header | X-Proxy-URL: http://... |
URL validation filtering. These represent various bypassable protection mechanisms.
| Value | Description | What It Blocks | Bypass Methods |
|---|---|---|---|
none |
No filtering | Nothing | N/A |
scheme_only |
Only allows specific URL schemes | Non-whitelisted schemes | IP addresses, DNS rebinding |
basic_host |
Blocks common internal hosts | localhost, 127.0.0.1, internal IPs | DNS rebinding, alternative representations |
Default:
none
When using scheme_only filter, specifies which URL schemes are allowed.
allowed_schemes: ["http://", "https://"]Default:
["http://", "https://"]
Whether to follow HTTP redirects (301, 302, etc.).
| Value | Behavior |
|---|---|
true |
Follow redirects (up to 10) |
false |
Return first response without following |
Default:
true
Request timeout in seconds.
timeout: 30 # 30 second timeout
timeout: 5 # 5 second timeout for port scanning detectionDefault:
30
Whether to include the response body in the output.
| Value | Behavior |
|---|---|
true |
Include response body (truncated at 10KB) |
false |
Only return status code and headers |
Default:
true
app:
name: "SSRF Lab 1"
port: 8081
endpoints:
- path: /fetch
method: GET
vulnerabilities:
- type: ssrf
placement: query_param
param: url
config:
filter: none
follow_redirects: true
return_body: true
timeout: 30app:
name: "SSRF Lab 2"
port: 8082
endpoints:
- path: /preview
method: GET
vulnerabilities:
- type: ssrf
placement: query_param
param: link
config:
filter: none
follow_redirects: true
return_body: trueapp:
name: "SSRF Lab 3"
port: 8083
endpoints:
- path: /webhook
method: POST
vulnerabilities:
- type: ssrf
placement: form_field
param: callback_url
config:
filter: none
follow_redirects: true
return_body: false # Don't need body for webhooksapp:
name: "SSRF Lab 4"
port: 8084
endpoints:
- path: /image-proxy
method: GET
vulnerabilities:
- type: ssrf
placement: query_param
param: src
config:
filter: none
follow_redirects: false
return_body: trueapp:
name: "SSRF Lab 5"
port: 8085
endpoints:
- path: /generate-pdf
method: POST
vulnerabilities:
- type: ssrf
placement: form_field
param: source_url
config:
filter: none
follow_redirects: true
return_body: trueapp:
name: "SSRF Lab 6"
port: 8086
endpoints:
- path: /api/fetch
method: POST
vulnerabilities:
- type: ssrf
placement: json_field
param: url
config:
filter: none
follow_redirects: true
return_body: trueapp:
name: "SSRF Lab 7"
port: 8087
endpoints:
- path: /safe-fetch
method: GET
vulnerabilities:
- type: ssrf
placement: query_param
param: url
config:
filter: scheme_only
allowed_schemes: ["http://", "https://"]
follow_redirects: trueapp:
name: "SSRF Lab 8"
port: 8088
endpoints:
- path: /proxy
method: GET
vulnerabilities:
- type: ssrf
placement: query_param
param: target
config:
filter: basic_host
follow_redirects: true
return_body: trueapp:
name: "SSRF Lab 9"
port: 8089
endpoints:
- path: /check
method: GET
vulnerabilities:
- type: ssrf
placement: query_param
param: url
config:
filter: none
timeout: 5 # Short timeout for port scanning
return_body: false # Only need connection status- Successful Request
{
"url": "http://example.com",
"status_code": 200,
"headers": {
"Content-Type": "text/html; charset=UTF-8",
"Server": "nginx"
},
"body": "<!DOCTYPE html>...",
"body_length": 1256
}- Connection Error
{
"url": "http://192.168.1.1:6379",
"error": "dial tcp 192.168.1.1:6379: connect: connection refused"
}- Blocked by Filter
{
"url": "http://127.0.0.1:8080",
"error": "access to internal hosts is not allowed",
"blocked": true
}- Timeout
{
"url": "http://10.0.0.1:22",
"error": "context deadline exceeded (Client.Timeout exceeded while awaiting headers)"
}The basic_host filter blocks common internal patterns but has bypasses:
Blocked patterns:
localhost-
127.0.0.1,127.0.0.0 0.0.0.0-
[::1](IPv6 localhost) -
169.254.x.x(link-local) -
10.x.x.x(private) -
192.168.x.x(private) -
172.16-31.x.x(private)
Bypass techniques:
# Decimal IP notation
http://2130706433 # = 127.0.0.1
# Octal notation
http://0177.0.0.1 # = 127.0.0.1
# Hex notation
http://0x7f.0x0.0x0.0x1 # = 127.0.0.1
# Mixed notation
http://127.1 # Short form
# IPv6 variations
http://[0:0:0:0:0:0:0:1]
http://[::ffff:127.0.0.1]
# DNS rebinding
http://attacker.com # Resolves to 127.0.0.1 after check
# Enclosed alphanumeric
http://127。0。0。1 # Unicode dots
# URL parsing tricks
http://127.0.0.1@evil.com
http://evil.com#@127.0.0.1Only blocks explicit localhost and 127.0.0.1:
# All of these bypass:
http://0.0.0.0
http://[::1]
http://127.0.0.2 # Different loopback
http://192.168.1.1 # Internal network
http://169.254.169.254 # Cloud metadataIf only http/https are allowed:
# These are blocked:
file:///etc/passwd
gopher://internal:25
# These bypass (still http/https):
http://127.0.0.1
http://169.254.169.254
https://internal-service