PHP İLE GÜVENLİ FORM İŞLEMEK VE İNJECTİON ÖNLEMEK
Web uygulamalarında formlar, kullanıcıyla temas eden en kritik yüzeylerden biridir. Bir “iletişim” ya da “kayıt” formu gibi basit görünen alanlar bile, zayıf doğrulama ve yanlış veritabanı kullanımıyla hızlıca güvenlik açığına dönüşebilir.
Bu yazıda PHP güvenli form işleme yaklaşımını adım adım ele alacağız. Hedef; veriyi doğru doğrulamak, güvenli şekilde saklamak ve çıktıyı güvenli üretmek. Böylece SQL injection, XSS ve CSRF gibi yaygın tehditleri pratik yöntemlerle azaltabileceksiniz.
İçerik boyunca gerçekçi örnekler, kontrol listeleri ve tekrar kullanılabilir küçük parçalar göreceksiniz. Ekibinizde standartlaştırabileceğiniz bir “güvenli form hattı” kurmaya odaklanacağız.

PHP güvenli form işleme yaklaşımını kurgulamak
Güvenli form işlemek, tek bir “filtre” eklemekten ibaret değildir. Sağlam bir yaklaşım; giriş doğrulama, güvenli veri erişimi, güvenli çıktı üretme ve istek bütünlüğünü korumayı birlikte ele alır.
Tehdit yüzeyini form alanlarına göre haritalamak
Hangi alanlar serbest metin kabul ediyor, hangileri sayısal, hangileri seçim listesi? Bu ayrımı netleştirmek; doğrulama kurallarını alan bazında tanımlamakla başlar. Örneğin “ad” alanı belirli karakter setine izin verirken, “yaş” alanı yalnızca sayı aralığı kabul etmelidir.
Sunucu tarafı doğrulama katmanı tasarlamak
İstemci tarafı kontroller kullanıcı deneyimini iyileştirir; ancak güvenlik için yeterli değildir. Sunucuda, gelen her alanı “beklenen tip” ve “beklenen format” ile doğrulamak gerekir. Bu katman; form doğrulama kurallarını tek noktada toplamakla sürdürülebilir hale gelir.
Input validation ile veri kalitesini güvenceye almak
Input validation, veriyi “temizlemekten” çok “kabul etmek” üzerine kurulur. Kabul edeceğiniz formatı tanımlayıp bunun dışındaki her şeyi reddetmek, hem güvenliği hem veri kalitesini artırır.
Whitelist doğrulama ile kabul edilebilir formatı tanımlamak
Örnek olarak e-posta, telefon ve sayısal alanlar için whitelist doğrulama kullanın. Bu, “yasaklı karakterleri çıkarma” yaklaşımına göre daha güvenilirdir. Çünkü saldırganın yeni bir varyasyonla kuralı aşma olasılığını azaltır.
Filtreleme ile normalize etmek ve hata mesajlarını yönetmek
Doğrulama başarısız olduğunda kullanıcıya anlaşılır, kısa ve yönlendirici mesajlar vermek gerekir. Aynı zamanda log tarafında daha ayrıntılı hata bağlamı tutarak ekip içi tanı koymayı hızlandırabilirsiniz. Hata mesajlarında hassas detay paylaşmamak önemlidir.
Prepared statement ile SQL injection riskini azaltmak
Veritabanına yazılan veya veritabanından okunan her değer için prepared statement kullanmak, SQL injection’a karşı temel savunmadır. “String birleştirme” ile sorgu üretmek, en küçük kaçırmada ciddi riske dönüşebilir.
PDO ile parametre bağlayarak güvenli sorgu çalıştırmak
Aşağıdaki örnek, tipik bir kayıt formundan gelen veriyi doğrulayıp PDO ile güvenli biçimde ekler. Bu örnekte hem doğrulama hem de güvenli veritabanı yazımı birlikte ele alınır.
<?php
declare(strict_types=1);
session_start();
function post(string $key): string {
return isset($_POST[$key]) ? trim((string)$_POST[$key]) : '';
}
$errors = [];
$name = post('name');
$email = post('email');
if ($name === '' || mb_strlen($name) < 2 || mb_strlen($name) > 80) {
$errors['name'] = 'Ad alanı 2-80 karakter olmalı.';
}
if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
$errors['email'] = 'E-posta formatı geçersiz.';
}
if (!hash_equals($_SESSION['csrf'] ?? '', post('csrf'))) {
$errors['csrf'] = 'İstek doğrulanamadı, tekrar deneyin.';
}
if ($errors) {
// Hataları kullanıcıya döndürürken detay sızdırmayın
http_response_code(422);
header('Content-Type: application/json; charset=utf-8');
echo json_encode(['errors' => $errors], JSON_UNESCAPED_UNICODE);
exit;
}
// PDO bağlantısı (örnek)
$pdo = new PDO(
'mysql:host=localhost;dbname=app;charset=utf8mb4',
'db_user',
'db_pass',
[
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
]
);
$stmt = $pdo->prepare('INSERT INTO contacts (name, email, created_at) VALUES (:name, :email, NOW())');
$stmt->execute([
':name' => $name,
':email' => $email,
]);
echo json_encode(['ok' => true], JSON_UNESCAPED_UNICODE);
?>Sorgu birleştirmeyi bırakmak ve loglamayı düzenlemek
Parametre bağlama kullanıldığında, saldırganın sorgu yapısını bozması zorlaşır. Ayrıca hata durumunda kullanıcıya “veritabanı hatası” gibi genel bir mesaj dönüp, ayrıntıyı log tarafında tutmak daha güvenlidir. Böylece operasyon ekibi için iz sürmek kolaylaşırken, dışarıya bilgi sızma riski azalır.

CSRF token ile istek bütünlüğünü korumak
CSRF, kullanıcının oturumu açıkken onun adına istek yaptırmayı hedefler. Özellikle form gönderen sayfalarda, CSRF token kullanmak ve token’ı sunucuda doğrulamak kritik bir adımdır.
Token üretmek ve form içine güvenli eklemek
Token üretimi için kriptografik olarak güvenli rastgelelik kullanın. Token’ı oturumda saklayıp form içine gizli alanla ekleyin. Bu token, her form gönderiminde sunucu tarafında karşılaştırılmalıdır.
Token doğrulamak ve yeniden üretmek
Token doğrulaması başarısız olursa isteği reddedin. Kritik işlemlerde token’ı periyodik olarak yenilemek ve aynı token’ın uzun süre kullanılmasını engellemek de faydalıdır. Bu yaklaşım, istek bütünlüğünü artırır.
XSS riskini azaltmak için output escaping uygulamak
XSS çoğu zaman “girişte temizleme” sanılır; oysa asıl kritik adım, veriyi ekrana basarken doğru bağlama göre kaçışlamakla başlar. HTML içinde gösterilecek metin ile HTML attribute içinde gösterilecek metin aynı şekilde ele alınmamalıdır.
htmlspecialchars ile güvenli çıktı üretmek
Aşağıdaki örnek, formdan gelen bir değeri ekranda güvenli biçimde göstermeyi amaçlar. Burada odak; veriyi “ne amaçla” çıktıladığınıza göre doğru kaçışlama yapmaktır.
<?php
declare(strict_types=1);
function e(string $value): string {
return htmlspecialchars($value, ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8');
}
$name = $_GET['name'] ?? '';
?>
<p>Merhaba, <strong><?= e($name) ?></strong>!</p>
<p>Bu sayfada gösterilen tüm kullanıcı girdileri, ekrana basmadan önce kaçışlanır.</p>Bağlama göre kaçışlamak ve şablonları disipline etmek
HTML gövdesi, attribute, URL parametresi veya JavaScript bağlamı farklı kaçışlama gerektirir. Basit projelerde bile “çıktı yardımcı fonksiyonu” kullanmak, ekip içinde standardı korur. Ayrıca şablonlarda çıplak kullanıcı girdisi göstermemek, review süreçlerini hızlandırır.

Güvenli form akışı için pratik kontrol listesi oluşturmak
Uygulamada hız kazanmak için her formda tekrar eden bir kontrol listesi kullanabilirsiniz. Aşağıdaki adımlar, form doğrulama ve güvenli veri akışı için temel bir çerçeve sunar.
Kontrol listesini ekiple standartlaştırmak
- Her alan için beklenen tip ve formatı tanımlamak
- Sunucu tarafında input validation uygulamak
- Veritabanı işlemlerinde prepared statement kullanmak
- CSRF token üretmek, saklamak ve doğrulamak
- Çıktıda bağlama göre output escaping yapmak
- Hata mesajlarında hassas detay paylaşmamak
Geliştirme sürecine test ve gözden geçirme eklemek
Formlar için otomatik testler yazmak, regresyon riskini düşürür. Özellikle doğrulama kuralları değiştikçe, beklenmeyen veri kabulü veya reddi yaşanabilir. Code review sırasında “sorgu birleştirme var mı”, “çıktıda kaçışlama var mı” gibi maddeler net kontrol noktalarıdır.
Performans ve kullanıcı deneyimi için güvenliği desteklemek
Güvenlik önlemleri kullanıcı deneyimini bozmak zorunda değildir. Doğru tasarlandığında, güvenlik hem hız hem de kalite açısından fayda sağlar. Örneğin sunucuda doğrulama şarttır; ancak istemci tarafı uyarılar kullanıcıyı daha hızlı yönlendirir.
Rate limiting ve bot trafiğini yönetmek
Özellikle giriş, kayıt ve iletişim formlarında kaba kuvvet veya spam trafiğiyle karşılaşabilirsiniz. Basit rate limiting, CAPTCHA veya davranışsal kontroller; kaynak tüketimini azaltır. Bu katmanlar, doğrulama ve veritabanı katmanına ulaşan kötü niyetli trafiği düşürür.
Gözlemlenebilirlik ile anomaliyi erken yakalamak
Form hatalarını, doğrulama başarısızlıklarını ve şüpheli istekleri ölçmek; saldırı denemelerini erken yakalamanıza yardımcı olur. Loglarda PII bilgilerini maskelemek, hem güvenlik hem uyumluluk açısından iyi bir pratiktir.
Ekibin hızlanması için tekrar kullanılabilir şablon kurmak
Tek bir formu güvenli hale getirmek iyi bir başlangıçtır; ancak asıl kazanç, bunu tüm projeye yayabilmektir. Doğrulama fonksiyonları, CSRF yardımcıları, çıktı kaçışlama ve veritabanı erişim katmanını küçük, test edilebilir parçalara ayırmak; bakım maliyetini düşürür.
Eğitimle ortak dil kurmak ve standartları yerleştirmek
Takım içinde aynı yaklaşımı benimsemek, hataları azaltır ve teslim hızını artırır. Uygulamalı örneklerle ilerleyen bir program, herkesin aynı kontrol listesini kullanmasını kolaylaştırır. Daha kapsamlı pratik için PHP eğitimi sayfasındaki içerik akışına göz atabilirsiniz.


