Ana Karargâh Neler Yapıyoruz?
Hikayemizin Perde Arkası Beyin Kıvılcımları Bağlantıya Geçin

Server-Side Request Forgery (SSRF) Güvenlik Önlemleri

Merhaba değerli okuyucular! Bugün, web uygulamalarının güvenliğinde önemli bir tehdit olan Server-Side Request Forgery (SSRF) saldırılarını ve bunlara karşı alınabilecek güvenlik önlemlerini detaylıca inceleyeceğiz. SSRF saldırılarının nasıl gerçekleştiğini anlamak ve etkili koruma yöntemlerini uygulamak, uygulamalarınızın güvenliğini önemli ölçüde artıracaktır. Hadi başlayalım!

SSRF Nedir?

Server-Side Request Forgery (SSRF), bir saldırganın sunucu tarafında yapılan istekleri manipüle ederek, normalde erişemeyeceği kaynaklara erişmesine olanak tanıyan bir güvenlik açığıdır. Bu saldırı türünde, saldırgan genellikle uygulamanın URL girdi alanlarını kullanarak, sunucuyu istenmeyen istekler yapmaya zorlar.

SSRF Saldırısı Örneği:


// Güvensiz kod örneği
const url = req.query.url;
fetch(url)
  .then(response => response.json())
  .then(data => res.json(data))
  .catch(error => res.status(500).json({ error: 'Bir hata oluştu' }));

Bu örnekte, kullanıcının sağladığı URL doğrudan kullanılıyor, bu da SSRF saldırılarına açık bir durum yaratıyor.

SSRF Saldırılarının Potansiyel Etkileri

  • İç ağ kaynaklarına erişim
  • Hassas verilerin sızdırılması
  • Uzaktan Kod Çalıştırma (RCE)
  • Port tarama ve servis keşfi
  • Diğer güvenlik önlemlerinin bypass edilmesi

SSRF Saldırılarını Önleme Yöntemleri

1. URL Doğrulama ve Filtreleme

Gelen URL'leri sıkı bir şekilde doğrulayın ve filtreleyerek sadece izin verilen kaynakları kabul edin.


const url = require('url');

function isValidUrl(inputUrl) {
    try {
        const parsedUrl = new URL(inputUrl);
        const allowedDomains = ['api.example.com', 'cdn.example.com'];
        return allowedDomains.includes(parsedUrl.hostname);
    } catch (error) {
        return false;
    }
}

// Kullanım
const userProvidedUrl = req.query.url;
if (isValidUrl(userProvidedUrl)) {
    // URL'yi kullan
} else {
    res.status(400).json({ error: 'Geçersiz URL' });
}

2. IP Adreslerini ve Özel Ağları Engelleme

İç ağ adreslerine ve özel IP aralıklarına yapılan istekleri engelleyin.


const ipRangeCheck = require('ip-range-check');

function isAllowedIp(ip) {
    const disallowedRanges = [
        '10.0.0.0/8',
        '172.16.0.0/12',
        '192.168.0.0/16',
        '127.0.0.0/8'
    ];
    return !ipRangeCheck(ip, disallowedRanges);
}

// Kullanım
const urlObj = new URL(userProvidedUrl);
const ip = await dns.promises.resolve(urlObj.hostname);
if (isAllowedIp(ip[0])) {
    // İsteği yap
} else {
    res.status(403).json({ error: 'Bu IP adresine erişim engellendi' });
}

3. Protokol Kısıtlaması

Sadece güvenli protokollere (örn. HTTPS) izin verin.


function isAllowedProtocol(inputUrl) {
    const parsedUrl = new URL(inputUrl);
    return parsedUrl.protocol === 'https:';
}

// Kullanım
if (isAllowedProtocol(userProvidedUrl)) {
    // İsteği yap
} else {
    res.status(400).json({ error: 'Sadece HTTPS protokolüne izin verilmektedir' });
}

4. Çıktı Kodlama

Sunucudan dönen yanıtları kodlayarak, hassas bilgilerin sızmasını engelleyin.


const sanitizeHtml = require('sanitize-html');

function sanitizeResponse(response) {
    return sanitizeHtml(response, {
        allowedTags: [],
        allowedAttributes: {}
    });
}

// Kullanım
fetch(validatedUrl)
    .then(response => response.text())
    .then(data => {
        const sanitizedData = sanitizeResponse(data);
        res.send(sanitizedData);
    });

5. Proxy Kullanımı

Tüm istekleri bir proxy üzerinden yönlendirerek ek bir güvenlik katmanı ekleyin.


const httpProxy = require('http-proxy');
const proxy = httpProxy.createProxyServer({});

app.use('/api', (req, res) => {
    const targetUrl = validateAndGetUrl(req.url);
    if (targetUrl) {
        proxy.web(req, res, { target: targetUrl });
    } else {
        res.status(400).send('Geçersiz URL');
    }
});

6. DNS Çözümleme ve Doğrulama

DNS çözümlemesi yaparak, istenen alan adının gerçekten beklenen IP adresine sahip olduğunu doğrulayın.


const dns = require('dns');

async function validateDomain(domain) {
    try {
        const addresses = await dns.promises.resolve(domain);
        const allowedIps = ['203.0.113.0', '203.0.113.1']; // Örnek IP'ler
        return addresses.some(ip => allowedIps.includes(ip));
    } catch (error) {
        return false;
    }
}

// Kullanım
const urlObj = new URL(userProvidedUrl);
if (await validateDomain(urlObj.hostname)) {
    // İsteği yap
} else {
    res.status(403).json({ error: 'Geçersiz domain' });
}

7. Rate Limiting

İstek sayısını sınırlayarak, potansiyel SSRF saldırılarının etkisini azaltın.


const rateLimit = require("express-rate-limit");

const limiter = rateLimit({
    windowMs: 15 * 60 * 1000, // 15 dakika
    max: 100 // Her IP için 15 dakikada maksimum 100 istek
});

app.use(limiter);

SSRF Güvenlik Kontrol Listesi

Uygulamanızın SSRF saldırılarına karşı güvenliğini sağlamak için bu kontrol listesini kullanabilirsiniz:


class SSRFSecurityChecker {
    constructor() {
        this.checks = {
            urlValidation: false,
            ipBlocking: false,
            protocolRestriction: false,
            outputEncoding: false,
            proxyUsage: false,
            dnsValidation: false,
            rateLimiting: false
        };
    }

    performUrlValidation() {
        // URL doğrulama implementasyonu
        this.checks.urlValidation = true;
    }

    implementIpBlocking() {
        // IP engelleme implementasyonu
        this.checks.ipBlocking = true;
    }

    restrictProtocols() {
        // Protokol kısıtlama implementasyonu
        this.checks.protocolRestriction = true;
    }

    enableOutputEncoding() {
        // Çıktı kodlama implementasyonu
        this.checks.outputEncoding = true;
    }

    setupProxy() {
        // Proxy kurulum implementasyonu
        this.checks.proxyUsage = true;
    }

    implementDnsValidation() {
        // DNS doğrulama implementasyonu
        this.checks.dnsValidation = true;
    }

    setupRateLimiting() {
        // Rate limiting implementasyonu
        this.checks.rateLimiting = true;
    }

    isSecure() {
        return Object.values(this.checks).every(check => check === true);
    }

    printSecurityStatus() {
        console.log("SSRF Security Status:");
        for (const [check, status] of Object.entries(this.checks)) {
            console.log(`${check}: ${status ? 'Implemented' : 'Not Implemented'}`);
        }
        console.log(`Overall Security: ${this.isSecure() ? 'Secure' : 'Not Secure'}`);
    }
}

// Kullanım örneği
const ssrfChecker = new SSRFSecurityChecker();
ssrfChecker.performUrlValidation();
ssrfChecker.implementIpBlocking();
ssrfChecker.restrictProtocols();
ssrfChecker.enableOutputEncoding();
ssrfChecker.setupProxy();
ssrfChecker.implementDnsValidation();
ssrfChecker.setupRateLimiting();
ssrfChecker.printSecurityStatus();

SSRF saldırıları, web uygulamaları için ciddi bir güvenlik tehdidi oluşturur. Ancak, doğru önlemler alındığında bu saldırıları etkili bir şekilde önlemek mümkündür. URL doğrulama, IP filtreleme, protokol kısıtlaması, çıktı kodlama ve diğer güvenlik önlemleri, SSRF saldırılarına karşı güçlü bir savunma hattı oluşturur.

Unutmayın ki, güvenlik sürekli bir süreçtir. Uygulamanızı düzenli olarak güvenlik açıklarına karşı test edin ve güncel güvenlik pratiklerini takip edin.

Siz SSRF saldırılarına karşı hangi önlemleri alıyorsunuz? Uygulamalarınızda karşılaştığınız zorluklar neler? Deneyimlerinizi ve düşüncelerinizi yorumlarda paylaşın!

Güvenli kodlamalar ve SSRF'siz bir dünya dilerim!