Uygulamanızda kullanıcı girişi yapıldı, rotalar korundu, her şey harika görünüyor değil mi? Ancak perde arkasında, kullanıcınızın oturumunu (session) kullanarak onun adına işlem yapabilen "hayalet bir saldırgan" olabilir. İşte bu saldırı modeline CSRF (Cross-Site Request Forgery) diyoruz.
CSRF Nedir? Oturumunuz Nasıl "Çalınır"?
CSRF (Siteler Arası İstek Sahteciliği), bir saldırganın, oturumu açık olan bir kullanıcıyı (farkında olmadan) kendi adına istenmeyen bir işlem yapması için kandırmasıdır.
(GENELLİKLE NERELERDE YAPILIR EKLENEBİLİR...)
Saldırı Nasıl Gerçekleşir?
Oturumun Açılması: Kullanıcı bankacılık veya e-ticaret sitenizde oturum açar. Tarayıcı, sunucudan bir session cookie (oturum çerezi) alır.
Kötü Amaçlı Site: Kullanıcı aynı tarayıcıda gezerken sahte bir siteye veya zararlı bir linke tıklar.
Gizli İstek: Bu sahte site, arka planda sizin gerçek sunucunuza bir
POSTisteği (örneğin: para gönder veya siparişi onayla) gönderir.Güven Boşluğu: Tarayıcı, sizin sitenize giden her istekte olduğu gibi, oturum çerezini otomatik olarak isteğe ekler. Sunucunuz isteği alır, çereze bakar ve "Evet, bu kullanıcı giriş yapmış, istek geçerli!" diyerek işlemi onaylar.
Özet: Sunucu, isteğin sizin gerçek sayfanızdaki bir butondan mı, yoksa saldırganın sahte sayfasındaki gizli bir koddun mu geldiğini ayırt edemez.
Çözüm: CSRF Token (Güvenlik Mührü)
Bu saldırıdan korunmanın en etkili yolu, her hassas isteğe (POST, PATCH, DELETE) tahmin edilemez ve tek kullanımlık bir mühür eklemektir.
Mantık Şudur: Sunucu, sizin her görünümünüz (EJS sayfası) için benzersiz bir CSRF Token üretir. Bu token formun içine gizli bir alan olarak yerleştirilir. Saldırgan sizin çerezinizi tarayıcı sayesinde otomatik gönderse bile, sunucunun o an ürettiği gizli token'ı asla bilemez.
Node.js ve Express.js ekosisteminde CSRF korumasını teknik bir iş akışıyla nasıl uygulayacağımızı adım adım inceleyelim.
1. csurf Paketinin Kurulumu
Express.js tabanlı uygulamalarda CSRF koruması sağlamak için endüstri standardı olan csurf paketini kullanıyoruz. İlk adım olarak terminal üzerinden ilgili paketi projenize dahil edin:
npm install --save csurf2. Sunucu Tarafı Yapılandırması ve Ara Yazılım (Middleware) Sıralaması
csurf paketi, çalışmak için bir oturum (session) veya çerez (cookie) mekanizmasına ihtiyaç duyar. Bu nedenle, CSRF ara yazılımını tanımlarken sıralama hayati önem taşır. CSRF koruması, oturum verilerine erişebilmesi için mutlaka express-session yapılandırmasından sonra kodlanmalıdır.
const csrf = require('csurf');
const session = require('express-session');
const csrfProtection = csrf();
// 1. Önce Session yapılandırılır
app.use(session({
secret: 'your_secret_key',
resave: false,
saveUninitialized: false
}));
// 2. Ardından CSRF koruması aktif edilir
app.use(csrfProtection);3. Verilerin Tüm Görünümlere (Views) Aktarılması: res.locals
Uygulamanızdaki her bir route (rota) için manuel olarak token göndermek yerine, Express'in res.locals nesnesini kullanarak bu veriyi otomatize edebiliriz. Bu yöntem, tanımlanan değişkenlerin tüm EJS şablonlarında doğrudan erişilebilir olmasını sağlar.
app.use((req, res, next) => {
// res.locals üzerinden tanımlanan veriler tüm şablon motorlarına iletilir
res.locals.isAuthenticated = req.session.isLoggedIn;
res.locals.csrfToken = req.csrfToken();
next();
});4. Frontend Entegrasyonu: Form İçinde Token Kullanımı
csurf ara yazılımı aktif edildiğinde, sunucu GET, HEAD ve OPTIONS dışındaki tüm HTTP isteklerinde (POST, PUT, DELETE vb.) geçerli bir token doğrulaması bekler. Token bulunmayan istekler sunucu tarafından reddedilecektir. Bu doğrulamayı sağlamak için formlarınızın içine _csrf isminde gizli bir girdi alanı eklemeniz gerekir.
<form action="/update-data" method="POST">
<input type="hidden" name="_csrf" value="<%= csrfToken %>">
<input type="text" name="data">
<button type="submit">Gönder</button>
</form>Teknik Kontrol Listesi
Uygulamanızın güvenliğini doğrulamak için şu teknik adımları kontrol edin:
Paket Bağımlılığı:
csurfpaketi projeye dahil edildi mi?Middleware Hiyerarşisi: CSRF ara yazılımı, oturum (session) yönetiminden sonra mı tanımlandı?
Global Değişken:
req.csrfToken()metodures.localsüzerinden tüm görünümlere servis edildi mi?Form Doğrulaması: Veri değişikliği yapan tüm
POSTformlarındaname="_csrf"özniteliğine sahip input alanı mevcut mu?
Bu yapılandırma tamamlandığında, sunucunuz her istekte tarayıcıdaki çerez ile formdan gelen token değerini karşılaştıracak ve yalnızca her iki veri de uyuştuğunda işlemin devam etmesine izin verecektir.
Modern Yaklaşım: React ve SPA Dünyasında CSRF
Geleneksel EJS yapısında sunucu, HTML sayfasını oluştururken token'ı doğrudan içine gömebilir. Ancak React veya Vue gibi modern bir SPA (Single Page Application) mimarisinde sunucunuz artık HTML değil, yalnızca ham veri (JSON) döndürür. Bu mimari değişim, "gizli input" mantığını devre dışı bırakırken, yerini çok daha esnek bir yöntem olan HTTP Header (Başlık) tabanlı doğrulamaya bırakır.
SPA Mimarisinde İş Akışı Nasıl Değişir?
Modern teknolojilerde süreç genellikle şu şekilde ilerler:
Token İsteği: React uygulaması başladığında veya kullanıcı giriş yaptığında, sunucudan bir CSRF token talep eder.
Header ile Gönderim: Frontend tarafı (örneğin Axios kullanarak), sunucuya yapacağı tüm
POST/PUT/DELETEisteklerinin başlığına (genellikleX-CSRF-Tokenismiyle) bu anahtarı ekler.Sunucu Doğrulaması: Sunucudaki
csurfara yazılımı, gelen isteğin gövdesine bakmak yerine bu özel başlığı (header) kontrol eder.Eğer başlık yoksa veya uyuşmuyorsa isteği reddeder.
Neden Daha Güvenli?
Bu yöntemin en güçlü yanı, SOP (Same-Origin Policy) ve CORS politikalarıdır. Başka bir siteden (örneğin saldırganın sitesinden) tetiklenen bir istek, sizin sunucunuza çerezleri otomatik olarak gönderse bile, o sitenin sizin özel HTTP başlıklarınızı (Header) okumaya veya manipüle etmeye yetkisi yoktur. Bu da savunma hattınızı bir katman daha güçlendirir.
Örnek: React + Axios Entegrasyonu
Backend tarafında token'ı sunduğunuzda, React tarafında yapmanız gereken tek şey bu mührü her isteğe otomatik olarak basmaktır:
import axios from 'axios';
// 1. Sunucudan token'ı alıyoruz
const fetchCsrfToken = async () => {
const { data } = await axios.get('/api/csrf-token');
// 2. Axios interceptor ile her POST isteğine bu header'ı ekliyoruz
axios.defaults.headers.post['X-CSRF-Token'] = data.csrfToken;
};
// Uygulama ayağa kalkarken çağrılır
fetchCsrfToken();Sonuç: Güvenlik Bir Tercih Değil, Standarttır
Web'in doğuştan gelen "unutkanlık" sorununu Cookies ve Sessions ile aştık; ancak bu çözümün getirdiği güvenlik risklerini de Hashing ve CSRF Token ile mühürledik. İster geleneksel EJS şablonları kullanın, ister modern bir React uygulaması geliştirin; kimlik doğrulama sisteminizin güvenliği, bu görünmez ama hayati koruma katmanlarına bağlıdır.