PHP'de SQL Injection nasıl engellenir?

akovskiniz

Kıdemli Üye
7 Ocak 2016
3,636
50
23
akovskiniz.php
p0qbke2.png

Konu içerisinde anahtar kelimeler renklendirilmiştir.

Merhabalar sevgili TurkHackTeam üyeleri, hack dünyasında en çok kullanılan SQL Injection saldırısını PHP kullanılan bir sistemde/projede nasıl engelleyebilirsiniz, bu konuyu bunu sizlere tam anlamıyla açıklamak adına açtım umarım işinize yarar.

Öncelikle SQL Injection dediğimiz kavram nedir, en yaygın şekilde var olan ve en çok zarar veren web uygulaması güvenlik açıklarından biridir. Bu açıktan korunmanın en kesin ve en güvenilir yolu ise parametreli SQL sorguları kullanmaktır. Parametreli sorgular, SQL ifadelerini önceden tanımlayarak geliştiricilere kolayca kullanma ve anlama imkanı sunar. Bu sayede kullanıcı girdilerini güvenli bir şekilde işleyebilir ve potansiyel saldırıları engelleyebiliriz.

Geliştiriciler, kullanıcı girdilerini temizlemek yerine özel karakterleri kaldırmaktan kaçınmalıdır çünkü bu tür korumalar, saldırganların atlayabileceği kod hilelerine yol açabilir. SQL Injection saldırılarından korunmak için geliştiriciler, parametreli sorguları kullanmaya devam etmelidirler.

Örnek bir parametreli SQL sorgusu

PHP:
// Bağlantı kodları baz alınmamıştır.

// Parametreli SQL sorgusu
$kullaniciAdi = "kullanici123";
$sifre = "gizli123";
$sql = "SELECT * FROM kullanicilar WHERE kullanici_adi = :kullaniciAdi AND sifre = :sifre";

// Sorguyu hazırla
$stmt = $db->prepare($sql);

// Parametreleri bağla
$stmt->bindParam(":kullaniciAdi", $kullaniciAdi, PDO::PARAM_STR);
$stmt->bindParam(":sifre", $sifre, PDO::PARAM_STR);

// Sorguyu çalıştır
$stmt->execute();

// Sonuçları al
$sonuclar = $stmt->fetchAll(PDO::FETCH_ASSOC);

// Sonuçların işlenmesi baz alınmamıştır.

PHP'de SQL Injection'ların engellenmesi
Web uygulamalarını herhangi bir dilde kodlarken, kullanıcı girdilerini (GET/POST/Headers/Cookie) güvensiz olarak kabul etmek ve ardından bu girdileri temizlemek yerine, SQL Injection saldırılarına karşı koruma sağlayan parametreli SQL yapılarını kullanmak en iyisidir. Aşağıdaki kod, basit bir PHP uygulamasını temsil eder. Bu uygulama GET veya diğer HTTP yöntemlerini kullanabilir ve MySQL veritabanı tablosu "users" ile çalışır.

users tablosu;
idusernamepasswordfirst_namelast_name
1akovskiniz$2y$10$1zvcD6d/YHBotnu20YY7FOKmSOrQxshznpOqwq2tWCI6k23e5vXG.AkovskinizTHT
2akovskiniztht$2y$10$wwF.H06rUN7PzXiVYJQIJeBkxrMaHYFK06DdRiVf2Y1WMOe2TDoLKArgeAkovskiniz
PHP:
<?php
/*
* 'id' parametresi girildiğinde bilgilerin hepsini görebiliriz
* Örnek - http://localhost/?id=1
*/

if (isset($_GET['id'])) {
    $id = $_GET['id'];

    $mysqli = new mysqli('localhost', 'dbuser', 'dbpasswd', 'sql_injection_example');
    if ($mysqli->connect_errno) {
        printf("Connect failed: %s\n", $mysqli->connect_error);
        exit();
    }

    $sql = "SELECT username FROM users WHERE id = $id";
    if ($result = $mysqli->query($sql)) {
        while($obj = $result->fetch_object()) {
            print($obj->username);
        }
    }

    elseif($mysqli->error) {
        print($mysqli->error);
    }
}
?>

Üstte bulunan koddaki sorunlar tek tek alt tarafta yazılmıştır, bu sorunların giderilmesi halinde sistem daha güvenli bir hal alacaktır;

1. Girdi Doğrulaması
Sorunun Açıklaması: Kimlik numarasının her zaman bir sayı olacağı bilinse de, kod bu girdiyi doğrulamaz. Kullanıcı girdisinin doğrulanması, SQL Injection'ı engellemese de, kötü niyetli kullanıcı verilerinin veritabanı tarafından yanlış yorumlanmasını önlemeye yardımcı olur.
Sorunun Çözümü: Veritabanı sorgusu işlenmeden önce kullanıcı girişini doğrulamak önemlidir. Giriş değerini sayı olup olmadığını kontrol etmek, güvenliği artırmamıza yardımcı olur.

2. Kod, SQL Injection'a izin veriyor
Sorunun Açıklaması: Kod, kullanıcı girdisini (örneğin, bir GET parametresi) doğrudan SQL ifadesine dahil ediyor. Bu, bir saldırganın SQL enjeksiyonu yaparak uygulamanın veritabanına zararlı bir sorgu göndermesine olanak tanır.
Sorunun Çözümü: Kullanıcı girdilerini içeren SQL sorgularıyla başa çıkmak için parametreli sorguları tercih edin. Parametreli sorgular, SQL sorgusunun kullanıcı girdilerini etkilemeyeceği bölümlerini önceden belirler.

3. Hatalar kullanıcıya gösteriliyor
Sorunun Açıklaması: Hataların görüntülenmesi, saldırganlara potansiyel bir SQL Injection saldırısını geliştirmek için bilgi sağlayabilir. Veritabanı türü ve sürümü gibi bilgiler, SQL Injection güvenlik açığını istismar etmeyi kolaylaştırabilir.
Sorunun Çözümü: SQL hatalarını kullanıcıya göstermekten kaçının. Hata mesajı gösterme gerekliliği varsa, hassas bilgiler içermeyen genel bir hata mesajı kullanın.

4. Hatalar günlüğe kaydedilmiyor
Sorunun Açıklaması: Hata günlükleri, sorunları tespit etmek ve olası saldırıları önlemek için önemlidir. Veritabanı hatalarını günlüğe kaydetmezseniz, önemli bilgi kaynaklarını kaçırabilirsiniz. Bu bilgiler, güvenlik açıklarını önceden tespit etmenize yardımcı olabilir.
Sorunun Çözümü: Veritabanı hatalarını kullanıcıya göstermek yerine, güvenli bir şekilde bir dosyaya kaydedin. Bu dosya, web sunucusu aracılığıyla erişilemez olmalıdır. Hataları PHP hata günlüğüne veya başka bir dosyaya kaydetmek iyi bir uygulamadır.

SONUÇ
Yani yapmanız gerekenler basit, SQL sorgularını parametrelendirin. Bu, sorguların güvenli ve anlaşılır olmasını sağlar. Parametreli sorgular, kullanıcı girdilerini güvenli bir şekilde işlemek için önemlidir. Sorgu tanımlandığında, kullanıcı tarafından sağlanan değişkenleri sorguda yer tutucular olarak kullanırız. Bu sayede veritabanı, kullanıcı girdileri ile SQL komutlarını ayırt edebilir. Bu, saldırganların SQL enjeksiyonu yapmasını engeller. Parametreleştirilmiş sorgular, tüm kullanıcı girdilerini veri olarak kabul eder ve komut olarak işlemez.
Parametreli sorgular, SQL Injection güvenlik açıklarını önler. PDO gibi araçlar, bu açığı kapatmada etkilidir. PDO, kullanımı kolay, taşınabilir ve adlandırılmış parametreleri destekler.

ctf0sk9.png
 
Üst

Turkhackteam.org internet sitesi 5651 sayılı kanun’un 2. maddesinin 1. fıkrasının m) bendi ile aynı kanunun 5. maddesi kapsamında "Yer Sağlayıcı" konumundadır. İçerikler ön onay olmaksızın tamamen kullanıcılar tarafından oluşturulmaktadır. Turkhackteam.org; Yer sağlayıcı olarak, kullanıcılar tarafından oluşturulan içeriği ya da hukuka aykırı paylaşımı kontrol etmekle ya da araştırmakla yükümlü değildir. Türkhackteam saldırı timleri Türk sitelerine hiçbir zararlı faaliyette bulunmaz. Türkhackteam üyelerinin yaptığı bireysel hack faaliyetlerinden Türkhackteam sorumlu değildir. Sitelerinize Türkhackteam ismi kullanılarak hack faaliyetinde bulunulursa, site-sunucu erişim loglarından bu faaliyeti gerçekleştiren ip adresini tespit edip diğer kanıtlarla birlikte savcılığa suç duyurusunda bulununuz.