NŞA’da PHP scriptler üzerinde iki yöntem ile zafiyet araştırmaları yapılabilir.

  1. Manuel Araştırma
  2. Otomatik Taramalarla

Biz bu makalede iki yöntemi de kullanarak temel anlamda PHP scriptlerde zafiyetler (SQLi, XSS, RCE, LFI vb.) nasıl keşfedilir ve nasıl exploit (sömürme) edilebilir bunlara değineceğiz.

SQL Injection Nedir?

Web uygulamalarında birçok işlem için kullanıcıdan alınan veri ile dinamik SQL cümlecikleri oluşturulur. Örneğin; “SELECT * FROM Products” örnek SQL cümleciği basit şekilde veritabanından web uygulamasına tüm ürünleri döndürecektir. Bu SQL cümlecikleri oluşturulurken araya sıkıştırılan herhangi bir meta-karakter SQL Injection’a neden olabilir.

Öncelikle örnek olması açısından SQL Injection açığı barındıran bir betik ile başlayalım.
Betiğimizin görevi; üye id’sine göre veritabanından o id’ye sahip üyenin bilgilerini ekrana yazdırmaktadır.

sqli isimli bir veritabanı oluşturdum ve içinde uye isimli bir tablo mevcut. Tablonun da 4 adet sütunu var. Sütunlar: id, username, password, email
Son olarak da içine örnek birkaç adet veri girişi yaptım:

Betiğimizi oluşturan uye.php dosyasının kodları aşağıdaki gibidir:

<?php 

$baglan = mysql_pconnect(“localhost”,”root”,”123456″);    / veritabanına bağlanıyoruz
$baglan = mysql_select_db(“sqli”,$baglan);    / oluşturduğumuz veritabanımızı seçiyoruz

$id = $_GET[“id”];
$sorgu = “SELECT * FROM uye WHERE id=”.$id;

$cek = mysql_fetch_object(mysql_query($sorgu)); 

echo ‘Olusan Sorgu: ‘.$sorgu.”<br>”;
echo $cek->username.”<br>”.$cek->email; 

?>

Bu betiği SQL Injection’a uğratan kod kısımlarını kırmızı renkle vurgulayarak gösterdim..
Böyle bir kod yazımı göstere göstere SQL Injection zafiyetine zemin oluşturmaktadır. Zafiyete neden olan id= query stringinin filtrelenmeden dinamik sql sorgusuyla birleştirilmesidir.

Manuel yolla ve genel olarak PHP scriptlerde SQL Injection zafiyetini yukarıdaki kod örneğindeki gibi tespitini yapabiliriz. Yani dinamik sorgu cümleciklerine ve hangi yöntemlerle sorgu çekildiklerine odaklanılmalıdır.

uye.php çalıştırıldığında görüldüğü gibi 1 id’sindeki bilgiler yani benim bilgilerim ekrana yazdırıldı:

Fakat zayıf bir kod yazım şekli kullandığımız için şimdi bunu SQL Injection saldırısına uğratalım, nasıl mı? id=1 ifadesinden sonra (tek tırnak) meta-karakterini kullanarak:

Sayfa Warning: mysql_fetch_object()… hatası verdi! Şimdi sıra geldi bunu sömürmeye yani exploit etmeye 🙂 Veritabanından hassas veriyi sızdırıyoruz:

Görüldüğü gibi bilgiler ekrana yansıdı:
username: ismailsaygili
password: iso123

Aynı exploiting işlemini bir de otomatize araç olan SQLMap ile exploit edelim:

Script üzerinde manuel yöntemle SQL Injection zafiyetini keşfetmiştik, şimdi de otomatik olarak RIPS yazılımı aracılığıyla PHP scriptler üzerinde zafiyet araştırması yapalım. Bu arada RIPS; PHP için statik kodlarda zafiyet analizi yapan bir yazılımdır.

RIPS Kurulumu ve Kullanımı

RIPS hiç bir kurulum gerektirmez! Tak-Çalıştır mantığı 🙂

Öncelikle RIPS’i buradan indirelim. rips klasörünü localhost’unuza kopyalayın ve web tarayıcınızla ilgili URL’e gidin:

1. Adımda: Taramak istediğiniz PHP scriptin klasör yolu belirtilir. Ben yukarıda örneğini yaptığımız betiğin klasör yolunu yazdım, çünkü şuan onu tarayacağız.

2. Adımda: Zafiyet tipi seçilir. Ben SQL Injection zafiyetini seçtim.

3. Adımda: subdirs’i seçersek belirttiğiniz klasör yolunun alt klasörleri de taranacaktır.

4. Adımda: Son olarak scan butonuna basarak taramayı başlatıyoruz.

Ben taramamı yaptım ve sonuç bu şekilde:

Görüldüğü üzere RIPS, 7. satırda SQL Injection zafiyeti tespit etti. Yukarıda biz manuel denetim yaparken keşfettik hatırladınız mı? 🙂

Hocam zayıf kodu paylaştınız, peki bu kodun güvenli hali nasıl yazılır?
Güvenli Kod 1:

<?php

$baglan = mysql_pconnect(“localhost”,”root”,”123456″);
$baglan = mysql_select_db(“sqli”,$baglan); 

$id = (int) intval($_GET[“id”]); // değişken tipi belirlenerek integer koruması sağlandı
$sorgu = “SELECT * FROM uye WHERE id=”.$id;
$cek = mysql_fetch_object(mysql_query($sorgu)); 

echo ‘Olusan Sorgu: ‘.$sorgu.”<br>”;
echo $cek->username.”<br>”.$cek->email;

?>

id değişkeninin tipini belirleyerek integer koruması sağlamış olduk. Yani saldırgan http://localhost/sqli/uye.php?id=1 URL’inden sonra tek tırnak meta-karakterini eklediğinde amacına ulaşamayacaktır çünkü id= query’sinden sonra sadece integer değerler kabul edilecektir. String yani karakter dizileri kabul edilemeyecektir.

Gördüğünüz gibi kullanıcı adı ve şifreyi veritabanından çekemiyoruz 🙁

SQL Injection’dan korunma tabi ki sadece bununla sınırlı değildir.. Örneğin id değişkeni mysql_real_escape_string fonksiyonu içine alınarak SQL sorguları için zararlı olabilecek karakterlerin başına ekler.

Diğer SQL Injection’dan Korunma Yöntemleri

  • Web uygulamalarında SQL Injection saldırısı yapmakta kullanılan komut ve karakterlerin geçişi engellenmelidir. Veri girişinin filtrelenmesi kadar veri çıkışının da incelenmesi web uygulamanın güvenliğini arttıracaktır.
  • Aşağıda belirtilen karakterlerin filtrelenmesi web uygulamanın SQL Injection ve olası diğer saldırılara karşı güvenliğini sağlayacaktır:
    • [‘],[<],[>],[;],[/],[?],[=],[&],[#],[%],[],[],[|],[@],[],[union],[exec],[select],[insert], [update],[delete],[drop],[sp],[xp],[“]
  • Veritabanı Bağlantılarının Yetkilerinin Düşürülmesi
    • Web uygulamanın veritabanına bağlanıp kayıtları okurken ve yazarken kullandığı hesabın yetkilerinin minimumda tutulması olası SQL Injection saldırısının zararlarını azaltacaktır.
  • Hata Mesajlarının Engellenmesi
    • Saldırganların hata mesajlarından bilgi almasını engellemek için hata mesajlarının görüntülenmesini engellemek sistemi daha güvenli hale getirecektir.
  • SA Hesabının Korunması
    • MS SQL sunucu üzerinde bulunan SA hesabının güçlü bir şifreye sahip olması brute-force saldırına karşı sistemin güvenliğini arttırmak için gerekli etkenlerden biridir. Web uygulamalarının SA hesabı ile veritabanına bağlanmasını engellemeliyiz! Olası SQL Injection sonucu saldırganın SA yetkilerinde kod çalıştırabileceğini unutmayınız.
  • Kaynak Kodların Kontrol Edilmesi
    • Web uygulamalarının kaynak kodlarının olası saldırılara karşı denetlenmesi gerekmektedir. Özellikle kullanıcının veri girişine müsade edilen alanlar ve URL alanında yapılabilecek değişikliklere karşı filtrelemelerin uygulanmasını sağlamalıyız.
  • Veritabanındaki Kayıtların Şifrelenmesi
    • Özellikle kullanıcıların şifrelerinin tutulduğu alanların şifrelenerek veritabanına yazılması olası veritabanındaki bilgilere ulaşılması durumuna karşı ekstra güvenlik sağlayacaktır.
  • Yazılımsal veya donanımsal olarak Web Application Firewall (WAF) kullanımı

Pekiştirmek açısından bir örnek daha yapmak istiyorum.
PHP script olan TopGames v1.2 sürümünde daha önceden SQL Injection açığı keşfedilmiş (http://www.exploit-db.com/exploits/26405/).

Haydi bunun sağlamasını RIPS ile tarayarak yapalım.. sonuç ortada:

SQL Injection dışında bir de Cross-Site Scripting (XSS) zafiyeti keşfettik 🙂

play.php dosyasının 4. satırında SQL Injection zafiyeti ($_GET[“gid“]) ve cat.php dosyasının 4. satırında ($_GET[“id“]) XSS zafiyeti mevcutmuş.

SQL Injection zafiyetini bu seferde Havij ile exploit edelim:

Bir de bulduğumuz XSS zafiyetini test edelim:

Sonuç başarılı…

TopGames scriptinde bulduğumuz XSS zafiyetini Exploit-DB’ye mi bildirsek ne? 🙂

Furkan SANDAL