💻 SQL Injection Nedir ve PHP ile Nasıl Önlenir? | Kapsamlı Rehber
Giriş
Web uygulamaları geliştirirken en kritik konulardan biri güvenliktir. Özellikle kullanıcıdan gelen verilerle çalışırken, uygulamanın dışarıdan gelecek zararlı komutlara karşı korunması hayati önem taşır. İşte bu noktada karşımıza SQL Injection tehlikesi çıkar. SQL Injection, kötü niyetli bir kullanıcının, veritabanı sorgularını manipüle ederek yetkisiz işlemler yapmasına olanak tanıyan bir güvenlik açığıdır.
PHP dilinde geliştirilen birçok projede, bu açık yüzünden kullanıcı bilgileri sızdırılabilir, veri kaybı yaşanabilir ya da sistem tamamen çökertilebilir. Bu nedenle, SQL Injection’ı doğru anlamak ve buna karşı alınabilecek önlemleri bilmek kritik öneme sahiptir. Bu yazıda, PHP dilinde SQL Injection’ın nasıl önleneceğini, kod örnekleriyle birlikte ayrıntılı bir şekilde ele alacağız.
SQL Injection’ın Temel Mantığı
SQL Injection, veritabanı sorgularında kullanıcıdan alınan verilerin doğrudan sorgu içerisine yerleştirilmesiyle oluşur. Kötü niyetli bir kullanıcı, bu boşluğu kullanarak veritabanına zararlı komutlar gönderebilir. Örneğin, bir kullanıcı giriş ekranında kullanıcı adı ve şifre bilgileri alınırken, doğrudan sorguya eklendiğinde aşağıdaki gibi bir yapı oluşur:
phpCopyEdit$username = $_POST['username'];
$password = $_POST['password'];
$query = "SELECT * FROM users WHERE username = '$username' AND password = '$password'";
Kullanıcı adının admin' --
şeklinde girildiğini düşünün. Bu durumda SQL sorgusu şu hale gelir:
sqlCopyEditSELECT * FROM users WHERE username = 'admin' --' AND password = ''
Bu durumda şifre kontrolü tamamen devre dışı kalır. Çünkü --
işareti SQL’de yorum satırı başlatır. Saldırgan, yalnızca kullanıcı adıyla sisteme giriş yapabilir.
SQL Injection Tehlikesinin Boyutları
SQL Injection sadece giriş sistemlerini tehdit etmez. Eğer bu açık sistem genelinde yaygınsa, saldırgan tüm veritabanına erişim sağlayabilir. Tablo yapıları, kullanıcı bilgileri, e-postalar, şifreler ve hatta sistem yapılandırmaları dahi ele geçirilebilir. Daha da kötüsü, DROP TABLE gibi komutlarla sistem tamamen yok edilebilir.
Birçok büyük kuruluş, yıllar içinde SQL Injection saldırılarına maruz kalmıştır. Bu da, sadece küçük projeler için değil, büyük ölçekli kurumsal sistemler için de bu tehdidin ne kadar ciddi olduğunu gösterir.
SQL Injection’dan Korunma Yolları
SQL Injection saldırılarına karşı alınabilecek birçok önlem vardır. Ancak bu önlemlerden bazıları temeldir ve neredeyse tüm sistemlerde uygulanmalıdır. PHP dilinde güvenlik için en etkili yöntemlerden biri prepared statements yani hazırlanmış ifadelerdir.
Prepared Statements ile Güvenli PHP Kodlama
Hazırlanmış ifadeler (prepared statements), kullanıcıdan gelen verileri doğrudan SQL sorgusuna dahil etmeden önce bu verileri özel olarak işler. Böylece, veri sadece bir parametre olarak ele alınır ve SQL komutunun bir parçası haline gelmez.
Bu yapı PDO (PHP Data Objects) veya MySQLi (MySQL Improved) kütüphanesi ile kullanılabilir. PDO, hem esneklik hem de güvenlik açısından daha tercih edilen yöntemdir.
PDO Kullanarak SQL Injection’dan Korunma
Aşağıda PDO kullanılarak hazırlanan bir kullanıcı giriş sistemi örneği yer almaktadır. Bu örnekte veritabanı bağlantısı, hazırlanan sorgular ve gelen verilerin güvenli işlenmesi ele alınmaktadır.
phpCopyEdit<?php
$host = 'localhost';
$db = 'veritabani_adi';
$user = 'kullanici_adi';
$pass = 'sifre';
$charset = 'utf8mb4';
$dsn = "mysql:host=$host;dbname=$db;charset=$charset";
$options = [
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
];
try {
$pdo = new PDO($dsn, $user, $pass, $options);
} catch (\PDOException $e) {
throw new \PDOException($e->getMessage(), (int)$e->getCode());
}
$username = $_POST['username'] ?? '';
$password = $_POST['password'] ?? '';
$stmt = $pdo->prepare('SELECT * FROM users WHERE username = :username AND password = :password');
$stmt->execute(['username' => $username, 'password' => $password]);
$user = $stmt->fetch();
if ($user) {
echo "Giriş başarılı. Hoşgeldiniz, " . htmlspecialchars($user['username']);
} else {
echo "Kullanıcı adı veya şifre hatalı!";
}
?>
Yukarıdaki örnekte dikkat edilmesi gereken en önemli nokta, sorgunun prepare()
metodu ile hazırlanması ve verilerin execute()
ile parametre olarak geçirilmesidir. Bu şekilde gönderilen veriler, SQL sorgusunun içine gömülmez ve enjekte edilemez.
🔐 MySQLi ile Hazırlanmış İfadeler Kullanarak SQL Injection Önleme
PHP’de MySQLi kütüphanesi ile de prepared statement kullanılabilir. Aşağıda, kullanıcı girişine dair güvenli bir örnek yer almaktadır:
phpCopyEdit<?php
$mysqli = new mysqli("localhost", "kullanici_adi", "sifre", "veritabani_adi");
if ($mysqli->connect_error) {
die("Bağlantı Hatası: " . $mysqli->connect_error);
}
$username = $_POST['username'] ?? '';
$password = $_POST['password'] ?? '';
$stmt = $mysqli->prepare("SELECT * FROM users WHERE username = ? AND password = ?");
$stmt->bind_param("ss", $username, $password);
$stmt->execute();
$result = $stmt->get_result();
if ($result->num_rows > 0) {
echo "Giriş başarılı!";
} else {
echo "Kullanıcı adı veya şifre hatalı!";
}
$stmt->close();
$mysqli->close();
?>
Açıklama
?
işaretleri, yer tutuculardır.bind_param()
fonksiyonu ile sorguya veriler güvenli bir şekilde bağlanır.ss
ifadesi, ikistring
parametre kullanıldığını belirtir.- Bu yöntemle sorguya dışarıdan müdahale edilmesi imkansız hale gelir.
🔒 Şifreleme (Hashing) ile Güvenliği Arttırmak
Giriş güvenliğinde yalnızca SQL Injection’dan korunmak yeterli değildir. Kullanıcı şifrelerinin de güvenli şekilde saklanması gerekir. Bu noktada PHP’nin password_hash()
ve password_verify()
fonksiyonları devreye girer.
Kayıt Olma Kısmı:
phpCopyEdit<?php
$password = $_POST['password'];
$hashed_password = password_hash($password, PASSWORD_DEFAULT);
// Veritabanına $hashed_password'ı kaydedin.
?>
Giriş Kısmı:
phpCopyEdit<?php
$entered_password = $_POST['password'];
$stored_hash = $user['password'];
if (password_verify($entered_password, $stored_hash)) {
echo "Giriş başarılı!";
} else {
echo "Şifre yanlış!";
}
?>
Bu yöntem sayesinde veritabanına düz şifre kaydedilmez. Şifre çözülemeyecek şekilde karma haline getirilir.
🛡️ Kullanıcı Verilerini Doğrulama ve Temizleme
Herhangi bir kullanıcı girişinden sonra mutlaka verileri doğrulamak gerekir. Örneğin:
phpCopyEdit$username = filter_input(INPUT_POST, 'username', FILTER_SANITIZE_STRING);
Bu kod sayesinde potansiyel zararlı karakterler temizlenir. Böylece hem SQL Injection hem de XSS gibi saldırılar büyük ölçüde engellenmiş olur.
htmlspecialchars()
fonksiyonu ise HTML çıkışlarında kullanıcı verilerini filtrelemek için kullanılır. Böylece kullanıcı tarafından girilen script tagleri gibi ifadeler etkisiz hale getirilir.
⚠️ XSS + SQL Injection Kombinasyonuna Karşı Önlemler
Bir saldırgan sadece veritabanına zarar vermekle kalmaz, aynı zamanda sisteme script yerleştirerek diğer kullanıcıları da hedef alabilir. Bu tür durumlara karşı verileri hem sunucu tarafında hem istemci tarafında kontrol etmek gereklidir.
Önerilen pratikler:
- Girişlerde
filter_input()
vehtmlspecialchars()
kullanımı - Çıkışlarda
htmlentities()
ile verilerin temizlenmesi - JavaScript içeren içeriklerin doğrudan HTML’e basılmaması
- CSRF token ile form doğrulama süreçlerinin güvence altına alınması
🧠 ORM Kullanarak SQL Injection’a Karşı Koruma
PHP geliştiricileri sıklıkla ORM (Object Relational Mapping) araçları kullanır. En popülerlerinden biri Eloquent ORM‘dir. Laravel gibi framework’lerde bulunan bu yapı, SQL sorgularını otomatik olarak güvenli hale getirir.
Örnek:
phpCopyEdit$user = User::where('email', $email)->first();
Bu sorguda kullanıcıdan gelen veriler otomatik olarak kaçış karakteri ile güvenli hale getirilir. ORM sistemleri, SQL Injection riskini minimize eder.
👨💻 Gerçek Hayattan SQL Injection Örnekleri
- Sony PlayStation Network (2011) – SQL Injection sonucu 77 milyon kullanıcının bilgisi sızdırıldı.
- Heartland Payment Systems – 130 milyon kredi kartı bilgisi SQL Injection ile ele geçirildi.
- Turkcell Benzeri Yerel Saldırılar – Forum siteleri, bloglar ve küçük e-ticaret platformları sık sık SQL Injection yüzünden kapanmak zorunda kaldı.
Bu saldırılar sadece maddi değil, aynı zamanda itibari zararlara da neden oldu.
🧪 PHP ile Güvenlik Testleri Nasıl Yapılır?
Web uygulamanızın güvenliğini manuel olarak test etmek mümkündür. Özellikle SQL Injection açısından aşağıdaki test teknikleri önemlidir:
1. Formlara Manuel Girişler
- Kullanıcı adı alanına:
' OR '1'='1
gibi klasik injection kalıpları girilerek davranış gözlemlenir. - Eğer sistem bu gibi sorgulara geçit veriyorsa, SQLi zafiyeti vardır.
2. Tarayıcı Eklentileri
- Burp Suite, OWASP ZAP gibi araçlar kullanılarak POST ve GET istekleri izlenebilir.
- Bu isteklerin içeriklerine SQLi payload’ları yerleştirilerek otomatik test yapılabilir.
3. SQLMap Kullanımı
Açık kaynak bir araç olan SQLMap ile SQLi güvenlik açıkları tespit edilebilir:
bashCopyEditsqlmap -u "http://site.com/index.php?id=1" --dbs
Bu komut ile id parametresi üzerinden veri tabanı isimleri çekilmeye çalışılır. Eğer başarılı olursa sistem savunmasızdır.
📌 OWASP İlkelerine Göre PHP Güvenliği
OWASP (Open Web Application Security Project), her yıl web güvenliğinde en tehlikeli 10 açığı yayınlar. SQL Injection bu listede her zaman üst sıralardadır. OWASP’e göre güvenli bir PHP uygulaması için şunlar uygulanmalıdır:
- Prepared Statement Kullanımı
- Girdi Doğrulama ve Temizleme
- Şifrelerin hash edilerek saklanması (bcrypt, Argon2)
- Doğru hata yönetimi (hata detaylarının kullanıcıya gösterilmemesi)
- Güvenli oturum yönetimi (session hijacking’e karşı önlemler)
- Veri çıkışında encode kullanımı
- CSRF token ile formları koruma
- Güncel PHP sürümleri kullanımı
- Minimum yetki ile çalışan DB kullanıcıları
- Güvenlik loglarının takibi
⚙️ PHP’de Güvenlik Açıkları ve Sık Yapılan Hatalar
💣 1. Dinamik SQL Kullanımı
phpCopyEdit$sql = "SELECT * FROM users WHERE username = '$username'";
Bu tarz dinamik ifadeler büyük bir güvenlik açığı oluşturur.
💣 2. Veritabanı Hatalarını Ekrana Basmak
phpCopyEditmysqli_query($conn, $sql) or die(mysqli_error($conn));
Bu tür hata mesajları, saldırganlara veritabanı yapısı hakkında bilgi verir.
💣 3. Girdi Doğrulamasını Sadece JavaScript’e Bırakmak
Kullanıcı tarafındaki doğrulama, tarayıcıda devre dışı bırakılabilir. Bu nedenle sunucu tarafı her zaman son savunmadır.
👷♂️ Proje Bazlı Gerçek Örnek: Kullanıcı Giriş Sistemi
1. Kayıt Sayfası (register.php)
phpCopyEdit<?php
$conn = new mysqli("localhost", "root", "", "test");
$username = $_POST['username'];
$password = password_hash($_POST['password'], PASSWORD_DEFAULT);
$stmt = $conn->prepare("INSERT INTO users (username, password) VALUES (?, ?)");
$stmt->bind_param("ss", $username, $password);
$stmt->execute();
echo "Kayıt başarılı.";
?>
2. Giriş Sayfası (login.php)
phpCopyEdit<?php
$conn = new mysqli("localhost", "root", "", "test");
$username = $_POST['username'];
$password = $_POST['password'];
$stmt = $conn->prepare("SELECT password FROM users WHERE username = ?");
$stmt->bind_param("s", $username);
$stmt->execute();
$result = $stmt->get_result();
if ($row = $result->fetch_assoc()) {
if (password_verify($password, $row['password'])) {
echo "Giriş başarılı!";
} else {
echo "Şifre hatalı.";
}
} else {
echo "Kullanıcı bulunamadı.";
}
?>
Bu örnek, SQL Injection’a karşı tamamen korumalıdır ve güncel şifreleme tekniklerini içerir.
📊 Güvenlik Log’larını Anlamak ve İzlemek
Her sistemin logları takip edilmelidir. Örnek bir loglama işlemi:
phpCopyEdit<?php
file_put_contents("log.txt", "Hatalı giriş: $username IP: $_SERVER[REMOTE_ADDR]\n", FILE_APPEND);
?>
Bu sayede saldırı girişimleri analiz edilebilir ve IP adresleri kara listeye alınabilir.
✅ CAPTCHA ve Doğrulama Sistemleri ile SQLi Önleme
Botlara karşı CAPTCHA kullanmak önemlidir. Google reCAPTCHA PHP ile kolayca entegre edilebilir.
htmlCopyEdit<form method="post" action="submit.php">
<!-- CAPTCHA alanı -->
<div class="g-recaptcha" data-sitekey="senin-site-key"></div>
<input type="submit" value="Gönder">
</form>
<script src="https://www.google.com/recaptcha/api.js" async defer></script>
Sunucu tarafında doğrulama:
phpCopyEdit$response = $_POST["g-recaptcha-response"];
$verify = file_get_contents("https://www.google.com/recaptcha/api/siteverify?secret=senin-secret-key&response=".$response);
$captcha_success = json_decode($verify);
if ($captcha_success->success == false) {
echo "Bot musun kardeşim?";
}
📘 Sonuç ve Öneriler
- Hazırlanmış ifadeler kullanmadan veri tabanı işlemi yapma.
- SQL sorgularını kullanıcı girdilerinden ayır.
- Kayıtlı verileri şifrelemeden saklama.
- Tüm kullanıcı giriş ve işlemlerini logla.
- Güvenlik açıklarını OWASP’e göre değerlendir.
PHP ile yazılan her uygulama, düzgün güvenlik kontrolleriyle SQL Injection’a karşı savunulabilir hale getirilebilir. Bu makalede verdiğimiz teknikler, hem küçük projelerde hem de kurumsal sistemlerde kullanılabilecek güvenli altyapılar sunar.
🔍 PDO vs MySQLi: Güvenlik ve Kullanılabilirlik Karşılaştırması
📌 Giriş
PHP’de veritabanı işlemleri için iki ana yaklaşım vardır: PDO (PHP Data Objects) ve MySQLi (MySQL Improved). Her iki yöntem de SQL Injection’a karşı koruma sağlayabilir, ancak bazı farkları bulunmaktadır.
🛡️ Güvenlik Açısından Karşılaştırma
Özellik | PDO | MySQLi |
---|---|---|
SQL Injection Koruması | ✔️ Hazırlanmış ifadeler ile tam koruma sağlar | ✔️ Hazırlanmış ifadeler ile koruma sağlar |
Parametre Bağlama | Evet (bindParam, bindValue) | Evet (bind_param) |
Veri Tipi Doğrulama | Otomatik | Manuel yapılmalı |
Desteklediği Veritabanı | 12+ farklı veritabanı (MySQL, PostgreSQL, SQLite, MSSQL…) | Sadece MySQL/MariaDB |
Hata Yönetimi | Exception tabanlı | Hata kontrolü manuel yapılır |
📎 PDO ile Güvenli Sorgu Örneği
phpCopyEdit<?php
$db = new PDO("mysql:host=localhost;dbname=testdb", "root", "");
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$stmt = $db->prepare("SELECT * FROM users WHERE email = :email");
$stmt->bindParam(':email', $_POST['email']);
$stmt->execute();
$user = $stmt->fetch(PDO::FETCH_ASSOC);
?>
📎 MySQLi ile Güvenli Sorgu Örneği
phpCopyEdit<?php
$conn = new mysqli("localhost", "root", "", "testdb");
$stmt = $conn->prepare("SELECT * FROM users WHERE email = ?");
$stmt->bind_param("s", $_POST['email']);
$stmt->execute();
$result = $stmt->get_result();
$user = $result->fetch_assoc();
?>
🔁 Sonuç
- PDO, esneklik ve veritabanı çeşitliliği bakımından avantajlıdır.
- MySQLi, sadece MySQL için optimize edilmiştir ve biraz daha hızlı olabilir.
- Her iki yöntem de SQL Injection’dan korunmak için yeterlidir ancak sadece hazırlıklı ifadeler (prepared statements) kullanıldığında!
🕵️♂️ Gerçek Hayattan SQL Injection Örnekleri
🎯 1. Ünlü Bir Veri Sızıntısı: Sony PlayStation Hack (2011)
- Saldırganlar SQL Injection ile kullanıcı verilerini ele geçirdi.
- Şifrelenmemiş kullanıcı adları, e-posta adresleri ve kart bilgileri çalındı.
- PHP ile geliştirilen sistemde, kullanıcı girişinde parametreler filtrelenmemişti.
🎯 2. Heartland Payment Systems (2008)
- 130 milyon kredi kartı bilgisi sızdırıldı.
- SQL Injection kullanılarak iç sistemlere girildi.
- Kodun zayıf noktası: doğrudan kullanıcı girdisi ile SQL oluşturulması.
🎯 3. Türkçe Örnek: Kamu Sitesinde SQL Injection Açığı
- Bir kamu kurumunun duyuru sisteminde, URL’de
id=1' OR '1'='1
gibi basit sorgularla erişim sağlandı. - MySQLi ile yazılmış sistemde prepared statements kullanılmamıştı.
🛠️ Laravel ve Symfony’de SQL Injection Önleme
Laravel (PHP Framework)
Laravel, Eloquent ORM ve Query Builder ile kullanıcı girişini doğrudan SQL’e dönüştürmeden işler.
phpCopyEdit$user = DB::table('users')->where('email', $email)->first();
ORM yapısı nedeniyle prepared statement arka planda otomatik olarak uygulanır. SQL Injection riski ortadan kalkar.
Symfony
Symfony, Doctrine ORM kullanır ve aynı şekilde SQLi’ye karşı koruma sağlar:
phpCopyEdit$user = $entityManager
->getRepository(User::class)
->findOneBy(['email' => $email]);
ORM kullanımı SQL ile etkileşimi en aza indirir, bu da güvenliği artırır.
🏰 Veritabanı Sunucusu Güvenliği
PHP’deki kod ne kadar sağlam olursa olsun, veritabanı sunucusunun da sağlam olması gerekir.
🔑 Yapılabilecek Güvenlik Ayarları:
- MySQL root hesabı kapatılmalı veya sadece localhost’ta erişime açılmalı.
- Veritabanı kullanıcılarına sadece ihtiyaç duydukları yetkiler verilmeli.
GRANT SELECT, INSERT ON mydb.* TO 'kullanici'@'localhost';
- MySQL sürümü güncel tutulmalı.
- Veritabanı dışarıya (0.0.0.0 gibi) açık olmamalı.
- Firewall ile 3306 portu dış erişime kapatılmalı.
🌐 API Güvenliğinde SQL Injection Önleme
🔍 RESTful API’lerde SQL Injection Riski
REST API’lerde istemcilerden gelen veri genellikle JSON formatındadır ve bu veri doğrudan SQL sorgularında kullanılabilir. Eğer bu veri uygun şekilde işlenmezse, arka uçta SQL Injection’a açık kapı bırakılabilir.
Tehlikeli bir örnek:
phpCopyEdit$data = json_decode(file_get_contents('php://input'), true);
$query = "SELECT * FROM users WHERE username = '{$data['username']}'";
Yukarıdaki gibi doğrudan yerleştirilen veri, API katmanında SQL Injection’a davetiye çıkarır.
✅ Güvenli RESTful API Örneği (PDO Kullanarak)
phpCopyEdit$data = json_decode(file_get_contents('php://input'), true);
$db = new PDO("mysql:host=localhost;dbname=testdb", "root", "");
$stmt = $db->prepare("SELECT * FROM users WHERE username = :username");
$stmt->bindParam(':username', $data['username']);
$stmt->execute();
$result = $stmt->fetch(PDO::FETCH_ASSOC);
echo json_encode($result);
Bu yöntem, API’nin dış dünyaya açık olmasından kaynaklı riskleri büyük ölçüde azaltır.
🛡️ Web Application Firewall (WAF) Kullanımı
🔥 WAF Nedir?
Web Application Firewall, web sunucusu ile internet arasına konumlanan ve zararlı trafiği engelleyen bir güvenlik katmanıdır.
📌 WAF’in SQL Injection’a Karşı Sağladığı Faydalar
- Anormal sorguları tespit eder (örneğin
' OR '1'='1
). - Bilinen SQL Injection imzalarına sahip trafiği otomatik olarak engeller.
- Gerçek zamanlı olarak loglama ve uyarı sağlar.
🚀 Popüler PHP Uygulamaları İçin WAF Örnekleri
- ModSecurity (Apache için)
- NAXSI (Nginx için)
- Cloudflare WAF (Bulut tabanlı)
- Sucuri (WordPress, Joomla gibi CMS’ler için)
🧪 Penetrasyon Testi (Pentest) ve Raporlama Süreci
⚙️ Test Süreci Nasıl İşler?
- Hedef Belirleme: Hangi URL’ler, API uç noktaları ve formlar test edilecek?
- Araç Kullanımı: SQLMap, Burp Suite, OWASP ZAP gibi araçlarla test gerçekleştirilir.
- Payload Denemeleri:
admin' OR '1'='1
,UNION SELECT
gibi ifadeler test edilir. - Sonuçların Analizi: Zayıflıklar belirlenir ve raporlanır.
- Öneri Sunumu: Hatalı yerler düzeltilir, güvenli yapı önerilir.
🧰 SQLMap ile Basit Bir Test
bashCopyEditsqlmap -u "http://example.com/page.php?id=1" --risk=3 --level=5 --dbs
Bu komut, hedef URL’deki id
parametresini test eder.
🧩 PHP Güvenlik Kütüphaneleri
PHP ekosisteminde güvenlik için kullanılabilecek bazı özel kütüphaneler mevcuttur. Bunlar, SQL Injection dışında XSS, CSRF gibi saldırılara karşı da koruma sağlar.
1. ParagonIE/AntiSQLi
- Kullanıcı girdilerini filtreler ve SQL Injection’a karşı özel koruma sağlar.
2. Defuse/PHP-Encryption
- Güvenli veri şifrelemesi sağlar; kullanıcı verisi veritabanına girmeden önce güvence altına alınır.
3. Symfony Security Component
- Symfony dışı projelerde de kullanılabilir, input doğrulama, yetkilendirme ve SQL Injection önlemlerini destekler.
🚨 En Sık Yapılan 20 SQL Injection Hatası
PHP geliştiricilerinin sıkça yaptığı bazı hatalar şunlardır:
- Kullanıcı girdisini doğrudan SQL sorgusuna yerleştirmek.
- Hazırlanmış ifadeler yerine
mysqli_query
veyamysql_query
kullanmak. - GET/POST verisini filtrelemeden işlemek.
- ORM kullanmamak.
- Veritabanı kullanıcılarına
ALL PRIVILEGES
vermek. - Hata mesajlarını kullanıcıya göstermek.
- Giriş formunda CSRF koruması olmaması.
addslashes()
fonksiyonuna güvenmek.- Girdi doğrulamasını yalnızca istemci tarafında yapmak.
- WAF kullanmamak.
- SQL hatalarını gizlemek yerine bastırmak.
- Dinamik SQL kullanırken değişkenleri kontrol etmemek.
- Loglama yapmamak.
- Eski MySQL uzantılarını (mysql_*) hâlâ kullanmak.
- Framework güvenlik ayarlarını devre dışı bırakmak.
- Session yönetimini güvenli yapmamak.
- API uçlarını yeterince korumamak.
- Erişim kontrollerini sadece frontend’e bırakmak.
- Girdileri escape ederek korunduğunu varsaymak.
- Kendi yazdığı ORM yapısına fazla güvenmek.
🎓 Sonuç ve Özet
SQL Injection, web uygulamaları için hâlâ en ciddi güvenlik tehditlerinden biridir. Özellikle PHP gibi esnek ve çok kullanılan bir dilde, geliştiricilerin güvenliğe daha fazla dikkat etmesi gerekir. Bu makalede:
- PHP ile SQL Injection nasıl oluşur?
- PDO ve MySQLi ile nasıl önlenir?
- Framework’ler bu konuda ne sağlar?
- API’lerde, WAF kullanımıyla ve penetrasyon testleriyle nasıl korunulur?
gibi konulara derinlemesine değindik.
✅ Anahtar Tavsiyeler:
- Her zaman prepared statement kullan.
- ORM tercih et.
- Veritabanı erişim izinlerini sınırlı tut.
- Pentest araçları ile düzenli denetim yap.
- Gerekiyorsa WAF gibi sistemler kurarak ekstra katman oluştur.
💼 Gerçek Hayat Senaryolarında SQL Injection
📍 1. E-Ticaret Sitesinde SQL Injection Vakası
Bir e-ticaret sitesi, ürün arama çubuğunda filtreleme parametrelerini SQL sorgusunda doğrudan kullandığı için saldırıya uğradı. Saldırgan, URL’ye eklediği ' OR 1=1 --
ile tüm ürün veritabanını listeleyip fiyatları değiştirmeye çalıştı.
📌 Güvenli Çözüm:
phpCopyEdit$category = $_GET['category'];
$stmt = $pdo->prepare("SELECT * FROM products WHERE category = :cat");
$stmt->bindParam(':cat', $category);
$stmt->execute();
📍 2. Üye Giriş Sistemi Hatası
Login formu, gelen kullanıcı adını şu şekilde sorguya ekliyordu:
phpCopyEdit$query = "SELECT * FROM users WHERE username = '$username' AND password = '$password'";
Bu yapı sayesinde "admin' -- "
gibi bir giriş ile parola kontrolü atlandı.
✅ Çözüm: Prepared Statement kullanmak
🔐 SQL Injection’a Karşı Güvenli Kodlama Standartları
✍️ Kod İnceleme Süreçlerinde Nelere Dikkat Edilmeli?
- Tüm SQL ifadelerinde dinamik veri varsa mutlaka
prepare
+bind
kullanılmalı. - ORM kullanılıyorsa bile, ORM’in query builder modülü dışında sorgular yazılmamalı.
- Herhangi bir raw SQL varsa, statik değilse kırmızı bayrak!
📂 Güvenli Kodlama Rehberleri
🔄 SQL Injection Loglama ve İzleme
SQL Injection girişimleri çoğu zaman loglardan tespit edilebilir. Loglama, saldırganın davranış kalıplarını anlamak için önemlidir.
🧠 PHP ile Basit Loglama Sistemi
phpCopyEditfunction log_suspicious_activity($msg) {
$logFile = fopen("suspicious.log", "a+");
fwrite($logFile, "[" . date("Y-m-d H:i:s") . "] " . $msg . "\n");
fclose($logFile);
}
$user_input = $_GET['search'];
if (preg_match('/\b(UNION|SELECT|--|DROP|INSERT|UPDATE|DELETE)\b/i', $user_input)) {
log_suspicious_activity("SQL Injection attempt: " . $user_input);
}
🧠 SQL Injection ve Yapay Zeka: Yeni Nesil Saldırı Algılama
🤖 Yapay Zeka Tabanlı Koruma Yöntemleri
- Makine Öğrenimi ile Anomali Tespiti:
- Normal kullanıcı sorgularının öğrenilmesi.
- Anormal kalıpların tanımlanması.
- AI-Driven WAF:
- Cloudflare, AWS Shield gibi yapay zekaya dayalı saldırı engelleyiciler.
- Log Analizi için NLP Uygulamaları:
- Log verileri doğal dil gibi analiz edilir.
- Saldırı içerikli sorgular otomatik etiketlenir.
📘 PHP’de SQL Injection’a Karşı Kurumsal Düzeyde Güvenlik Mimarisi
Kurumsal projelerde aşağıdaki mimari yapılar önerilir:
1. Katmanlı Mimari (Layered Architecture)
- Controller: Girdiyi alır.
- Service: İş mantığını yürütür.
- Repository: PDO gibi araçlarla veritabanı işlemi yapar.
2. Dependency Injection ile Güvenlik
- PDO objesi, merkezi güvenlik ayarları ile projeye entegre edilir.
3. Config Tabanlı Güvenlik Yönetimi
- Tüm SQL güvenlik kuralları bir config dosyasından yönetilir.
- Örneğin: phpCopyEdit
return [ 'allowed_tables' => ['users', 'products'], 'allowed_operators' => ['=', '<', '>'], ];
🔍 SQL Injection’ın Yasal ve Etik Boyutu
⚖️ Hukuki Sonuçlar
SQL Injection saldırısı gerçekleştiren kişi:
- Türk Ceza Kanunu (TCK) 244. Madde gereği hapis cezasına çarptırılabilir.
- Veritabanına zarar verildiyse ceza daha da ağırlaşır.
👨💻 Beyaz Şapkalı Hacker (Etik Hacker) Ne Yapar?
- Açığı belirler ve işletmeye rapor eder.
- Yasal zeminlerde (Bug Bounty, Pentest sözleşmesi) çalışır.
- SQL Injection gibi zafiyetleri sorumlulukla bildirir.
🎯 Final Özet: En Güçlü Koruma Yöntemleri
Yöntem | Açıklama |
---|---|
PDO Prepared Statement | SQL enjeksiyonlara karşı en etkili koruma |
ORM Kullanımı | Laravel, Symfony gibi framework’lerle güvenli sorgular |
WAF | ModSecurity, Cloudflare gibi çözümlerle ek katman |
AI Destekli İzleme | Saldırıları öğrenip engelleyen sistemler |
Loglama & Alarm | Şüpheli hareketleri anlık bildirimlerle yakalama |
Tşk
Review SQL Injection Nedir ve PHP ile Nasıl Önlenir? | Kapsamlı Rehber.