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

Cross-Site Request Forgery (CSRF) Tokenları ile Güvenlik

Merhaba değerli okuyucular! Bugün, web uygulamalarının güvenliğinde kritik bir rol oynayan Cross-Site Request Forgery (CSRF) saldırılarına karşı etkili bir savunma yöntemi olan CSRF tokenlarını derinlemesine inceleyeceğiz. Bu önemli güvenlik önleminin nasıl uygulanacağını ve neden bu kadar önemli olduğunu detaylıca ele alacağız. Hazırsanız, web güvenliğinin bu önemli konusuna dalalım!

CSRF Nedir?

Cross-Site Request Forgery (CSRF), bir saldırganın, oturum açmış bir kullanıcının tarayıcısını kullanarak, kullanıcının bilgisi veya izni olmadan istekler göndermesine neden olan bir saldırı türüdür. Bu saldırılar, kullanıcının kimlik bilgilerini kullanarak, hassas işlemleri (örneğin, para transferi, şifre değiştirme) gerçekleştirebilir.

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


<!-- Kötü niyetli bir web sitesinde gizlenmiş form -->
<form action="https://bank.com/transfer" method="POST">
    <input type="hidden" name="amount" value="1000">
    <input type="hidden" name="to" value="hacker-account">
    <input type="submit" value="Kazanmak için tıkla!">
</form>

<script>
    document.forms[0].submit(); // Otomatik form gönderimi
</script>

Bu örnekte, kullanıcı kötü niyetli siteyi ziyaret ettiğinde, banka hesabından para transferi otomatik olarak gerçekleştirilmeye çalışılır.

CSRF Tokenları Nedir?

CSRF tokenları, her form veya AJAX isteği için benzersiz ve tahmin edilemez değerler oluşturarak, bu tür saldırıları önlemeye yardımcı olan bir güvenlik önlemidir. Token, sunucu tarafında oluşturulur, istemciye gönderilir ve her istekle birlikte sunucuya geri gönderilir. Sunucu, gelen isteğin geçerli bir token içerip içermediğini kontrol eder.

CSRF Tokenlarının Çalışma Prensibi

  1. Sunucu, benzersiz bir token oluşturur.
  2. Token, form içinde gizli bir alan olarak veya JavaScript ile AJAX isteklerine eklenir.
  3. Kullanıcı formu gönderdiğinde veya AJAX isteği yaptığında, token da gönderilir.
  4. Sunucu, gelen tokeni doğrular.
  5. Token geçerliyse işlem devam eder, değilse reddedilir.

CSRF Token Uygulaması

1. PHP ile CSRF Token Oluşturma ve Doğrulama


<?php
session_start();

function generateCSRFToken() {
    if (!isset($_SESSION['csrf_token'])) {
        $_SESSION['csrf_token'] = bin2hex(random_bytes(32));
    }
    return $_SESSION['csrf_token'];
}

function verifyCSRFToken($token) {
    if (!isset($_SESSION['csrf_token']) || $token !== $_SESSION['csrf_token']) {
        die('CSRF token doğrulaması başarısız.');
    }
}

// Form sayfasında
$csrf_token = generateCSRFToken();
?>

<form method="POST" action="process.php">
    <input type="hidden" name="csrf_token" value="<?php echo $csrf_token; ?>">
    <!-- Diğer form alanları -->
    <input type="submit" value="Gönder">
</form>

<?php
// İşlem sayfasında (process.php)
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    verifyCSRFToken($_POST['csrf_token']);
    // İşleme devam et...
}
?>

2. JavaScript ile AJAX İsteklerinde CSRF Token Kullanımı


// HTML
<meta name="csrf-token" content="<?php echo $csrf_token; ?>">

// JavaScript
const csrfToken = document.querySelector('meta[name="csrf-token"]').getAttribute('content');

fetch('/api/data', {
    method: 'POST',
    headers: {
        'Content-Type': 'application/json',
        'X-CSRF-TOKEN': csrfToken
    },
    body: JSON.stringify(data)
})
.then(response => response.json())
.then(data => console.log(data));

3. Python (Django) ile CSRF Koruması


# settings.py
MIDDLEWARE = [
    'django.middleware.csrf.CsrfViewMiddleware',
    # ...
]

# views.py
from django.views.decorators.csrf import csrf_protect

@csrf_protect
def my_view(request):
    # View logic here
    pass

# template.html
<form method="POST">
    {% csrf_token %}
    <!-- Form fields -->
    <input type="submit" value="Submit">
</form>

CSRF Token Uygulamasında Best Practices

1. Token'ları Güvenli Bir Şekilde Oluşturun

Kriptografik olarak güçlü rastgele sayı üreticileri kullanın.


// PHP
$token = bin2hex(random_bytes(32));

// Python
import secrets
token = secrets.token_hex(32)

// Node.js
const crypto = require('crypto');
const token = crypto.randomBytes(32).toString('hex');

2. Token'ları Oturum Bazlı Saklayın

Her kullanıcı oturumu için ayrı bir token kullanın ve sunucu tarafında saklayın.

3. Token'ları Düzenli Olarak Yenileyin

Güvenliği artırmak için token'ları belirli aralıklarla yenileyin.


function refreshCSRFToken() {
    $_SESSION['csrf_token'] = bin2hex(random_bytes(32));
    $_SESSION['csrf_token_time'] = time();
}

function isCSRFTokenExpired() {
    $expiry_time = 30 * 60; // 30 dakika
    return (time() - $_SESSION['csrf_token_time']) > $expiry_time;
}

if (isCSRFTokenExpired()) {
    refreshCSRFToken();
}

4. Double Submit Cookie Yöntemi

Token'ı hem cookie'de hem de form/header'da göndererek ek bir güvenlik katmanı ekleyin.


// Token'ı cookie'ye ayarla
setcookie('csrf_token', $token, ['httponly' => true, 'samesite' => 'Strict']);

// İsteği doğrula
if ($_COOKIE['csrf_token'] !== $_POST['csrf_token']) {
    die('CSRF token doğrulaması başarısız.');
}

5. SameSite Cookie Attribute Kullanın

CSRF korumasını güçlendirmek için SameSite cookie özelliğini kullanın.


setcookie('session_id', $session_id, [
    'httponly' => true,
    'samesite' => 'Strict',
    'secure' => true
]);

CSRF Korumasının Ötesinde: Ek Güvenlik Önlemleri

1. Content Security Policy (CSP) Uygulayın

CSP, XSS saldırılarını önlemeye yardımcı olur ve dolaylı olarak CSRF'yi de zorlaştırır.


header("Content-Security-Policy: default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval'; style-src 'self' 'unsafe-inline';");

2. X-Frame-Options Header'ı Kullanın

Clickjacking saldırılarını önleyerek, CSRF saldırılarının bazı formlarını engeller.


header('X-Frame-Options: DENY');

3. Önemli İşlemler için Yeniden Kimlik Doğrulama

Hassas işlemler için kullanıcıdan şifresini tekrar girmesini isteyin.

CSRF Token Uygulamasında Yaygın Hatalar

1. Token'ı URL'de Göndermek

Token'ları asla URL parametresi olarak göndermeyin, çünkü bu şekilde token'lar loglarda ve tarayıcı geçmişinde görünebilir.

2. Zayıf Token Üretimi

Tahmin edilebilir veya zayıf token'lar kullanmaktan kaçının.

3. Token Doğrulamasını Atlamak

Tüm POST, PUT, DELETE gibi state-changing isteklerde token doğrulaması yapın.

4. HTTPS Kullanmamak

CSRF token'larını her zaman HTTPS üzerinden gönderin.

Güvenli Web Uygulamaları için CSRF Koruması

CSRF tokenları, web uygulamalarınızı Cross-Site Request Forgery saldırılarına karşı korumada kritik bir rol oynar. Doğru bir şekilde uygulandığında, bu tokenlar kullanıcılarınızın hesaplarını ve verilerini korumada oldukça etkilidir.

Ancak, CSRF koruması tek başına yeterli değildir. Güvenli bir web uygulaması geliştirmek için, CSRF tokenlarını diğer güvenlik önlemleriyle birlikte kullanmalı ve sürekli olarak güvenlik pratiklerinizi güncellemelisiniz.


class WebSecurityManager {
    private $csrf_token;

    public function __construct() {
        $this->initCSRFProtection();
    }

    private function initCSRFProtection() {
        if (!isset($_SESSION['csrf_token'])) {
            $_SESSION['csrf_token'] = bin2hex(random_bytes(32));
        }
        $this->csrf_token = $_SESSION['csrf_token'];
    }

    public function getCSRFToken() {
        return $this->csrf_token;
    }

    public function verifyCSRFToken($token) {
        if (!hash_equals($this->csrf_token, $token)) {
            throw new SecurityException('CSRF token doğrulaması başarısız.');
        }
    }

    public function setSecurityHeaders() {
        header("Content-Security-Policy: default-src 'self';");
        header('X-Frame-Options: DENY');
        header('X-XSS-Protection: 1; mode=block');
        header('X-Content-Type-Options: nosniff');
    }
}

$securityManager = new WebSecurityManager();
$securityManager->setSecurityHeaders();

// Form oluştururken
echo '';

// Form işlerken
try {
    $securityManager->verifyCSRFToken($_POST['csrf_token']);
    // İşleme devam et...
} catch (SecurityException $e) {
    // Hata işleme...
}

Siz uygulamalarınızda CSRF koruması kullanıyor musunuz? Hangi yöntemleri tercih ediyorsunuz? CSRF saldırılarına karşı başka hangi önlemleri alıyorsunuz? Deneyimlerinizi ve düşüncelerinizi yorumlarda paylaşın!

Güvenli kodlamalar ve her zaman korumalı istekler!