OWASP TOP 10 A1-2017-Injection SQL... - Gais Security- Gais Siber Güvenlik Teknolojileri

OWASP TOP 10 A1-2017-Injection SQL Injection Nedir?

SQL nedir, çeşitleri nelerdir?

SQL, veritabanını yönetmek  için kullanılan bir veritabanı yönetim(sorgu) dilidir. SQL ile veritabanı üzerinde işlemler yapılır ve esnek bir biçimde verilerin yönetimini  kolaylaştırır. Bunları kendi içerisindeki çeşitli söz dizimleri   ile  yapar. Bu  söz  dizimleri ve komutları SQL sorgu dilini oluşturur.

SQL sorgu dili birçok platformda farklı yazılım ürünleri ile kullanılmaktadır. En yaygın örnekleri Microsoft SQL Server, Oracle, Mysql, Postgresql ürünleridir. Bu farklı platformlar, sql söz dizimi ve anlam açısından birbirine çok benzesede, bazı kurallarda bir birinden oldukça farklı yapılar olduğu söylenebilir. Yaygın olarak kullanılan  bu veritabanı yönetim sistemleri, amaca uygun olarak çeşitli birçok platformda kullanılırlar. Ortak amaç verilerin erişilebilmesi, gizliliği ve  yönetilebilmesidir.

SQL Injection nedir?

Saldırganların SQL dilinden faydalanarak veritabanlarına yönelik gerçekleştirdiği saldırı yöntemidir. Bu saldırıları yapabilmek için özünde birçok sql söz dizimini ve nasıl çalıştığını iyi bilmek gerekir. SQL injection saldırıları, veritabanı ile dinamik biçimde iletişim halinde olan her uygulamada karşımıza çıkabilmektedir. Bunlar web uygulamarı, masaüstü uygulamaları, mobil uygulamaları gibi günlük yaşamımızda çok sık kullandığımız platformlar olabilmektedir.

SQL injection saldırıları, kullanıcı ile sunucu arasında gidip gelen çeşitli sql söz dizimlerine müdahalede bulunup, giden söz dizimini saldırganın kendi amaçları doğrultusunda değiştirip, veritabanında çeşitli işlemler yapabildiği bir saldırı çeşitidir.

Bazı SQL deyimleri ve anlamları.

SQL deyimleri, veritabanları üzerinde çeşitli işlemleri yerine getirir. Farklı farklı SQL yazılımlarının standardizasyonuna  baktığınızda, sql komut ve deyimlerinin derya deniz olduğunu görürsünüz. Bu deyimlere  ve kullanımlarına ne kadar hakim olabilirsek, karşılaşacağımız sql tabanlı zafiyetlere o kadar akılcı yaklaşabiliriz. SQL söz diziminin anlaşılabilmesi için basit ve ilk etapta  anlaşılabilirliği olan Mysql yazılımı üzerinde çalışmak istediğimizi  varsayarak ve bunun üzerine konuyu genişleterek devam edelim. Aşağıda yazılan söz dizimleri ve deyimler Mysql yazılımı üzerinde geçerliliği olmakla birlikte, diğer SQL yazılımlarında da konu üç aşağı beş yukarı aynı sentaks yapısındadır. (standardizasyon açısından çok büyük farklar da olabilir.)

SELECT deyimi veritabanı üzerinde çeşitli sorgulamalar yapmak için kullanılmaktadır. Örnek teşkil etmesi açısından şu söz dizimi yorumlayabiliriz.

SELECT id FROM haberler

Burada select deyimi haberler tablosundaki “id” kolonuna  sorgu yapmaktadır. Bu söz dizimi ile haberler tablosundaki id kolonundaki verilere erişebiliriz. Farkındaysak SELECT den sonra id, sonrasında FROM, sonrasındaysa haberler yazdık. Aslında gönderilen sentaks yapısına baktığımızda çok basit düşünerek sorgunun ne yaptığını kavrayabiliriz. “haberler tablosundaki id kolonundaki verileri getir”. Peki id değeri yerine farklı bir space kullanabilirmiyiz? Örneğin yıldız “*”  (star) karakteri yazılırsa söz dizimi, veritabanı yazılımına ne emir vermiş olur? Buna bakalım.

SELECT * FROM haberler

“Haberler tablosundaki tüm kolonlarda var olan verileri getir”. Burada yıldız karakterini kullanarak tüm kolonları kapsadığımızı belirtiyoruz. Haberler tablosundaki tüm kolonlar ve içeriğine erişim sağlayabilmiş oluyoruz. 

 CREATE deyimi ve yanına ekleyeceğimiz TABLE veya DATABASE gibi deyimler ile gerek tablo gerek veritabanları oluşturabiliriz. Bunun için en basit söz deyimi yapısına göz atalım.

CREATE TABLE forum_kullanicilari;

Sentaks yapısına baktığımızda “forum_kullanicilari” adında bir tablo oluşturmasını söyledik. En basit ifade ile bunu yaptık. Aynı biçimde,  basit bir söz dizimi ile veritabanı oluşturabiliriz.

CREATE DATABASE  forum_db;

Bu sentaks yapısında ise “forum_db” adında bir veritabanı oluşturmasını söyledik.

Oluşturduğumuz yapıları DROP komutu ile silebilmekteyiz.

DROP TABLE forum_kullanicilari;

Sözdizimi  yürütüldüğünde  ilgili tabloyu silmiş oluyoruz. Gözümüzün önüne şöyle bir sentaks yapısı getirelim.

SELECT * FROM uye WHERE id = 1 OR id=2;

Bu sentaks yapısında “uye tablosunda, kolonlardan id isimli olanından, kayıt değeri 1 veya 2 olanı getir” dedik. Pekala getirilen değerlerin alfabetik sıraya göre A’dan Z’ye veya tam tersi Z’den A’ya sıralanması isteseydik, ne biçimde bir sentaks yapısı oluşturmamız gerekirdi. Buna bakalım.

SELECT * FROM uye WHERE id =1 OR id=2 ORDER BY ASC;

Sentaks yapısına ORDER BY deyimini yerleştirip yanına ASC deyimini yazdık. ASC deyimi, örneğini verdiğimiz A’dan Z’ye sıralama işlemini yapar. Z’den A’ya bir sıralama yapmak isteseydik ASC deyimi yerine DESC deyimini kullanacaktık. ORDER BY deyimini kullandık fakat işin bir ince noktasını kaçırmayalım. Order by ile sıralamayı belirli bir kolon üzerine yaptırtabilir miydik? Sorunun cevabı evet. Açıklamak gerekirse, Sentaks yapısında “uye” tablosu üzerinde işlemler yapılmaktadır. Biz üye tablosunda var olan kullanıcıların isimlerinin “ad” veya “ad_soyad” kolonunda tutulduğunu düşünelim. Adı A’dan başlayıp Z’ye kadar olan üyelerin sıralamasını yapmak isteseydik şöyle bir sentaks yapısı oluşturmamız gerekecekti.

SELECT * FROM uye WHERE id=1 ORDER BY ad ASC; 

ORDER BY deyiminin, mysql  yazılımını geliştiren firmanın yayınladığı standardizasyonundaki bildirimine  bakarsanız ORDER BY deyiminden sonra bir kolon adı veya kolonun sıra numarasının da gelebileceğini görebilirsiniz.

Veritabanında yer alan herhangi bir tabloda var olan verilerin yanına başka bir veri eklenmesi için gereken sql sentaks yapısı ve kullanılması gereken deyim INSERT INTO olacaktır. INSERT INTO deyiminden sonra tablo adı ve sırasıyla VALUES deyimi ve kolonlara sıra ile hangi verinin işleneceği bilgileri girilecektir. Bu gibi durumlarda elimizdeki sentaks yapısı şöyle olacaktır.

INSERT INTO tablo_adı (kolon1, kolon2) VALUES (deger1,deger2);

Önceden oluşturulmuş olan uye tablosuna bir kullanıcı bilgisi eklemek istediğimizde  INSERT INTO uye(id,ad,soyad,email,kullanici_adi,parola) VALUES (5,”AHMET”,”YILMAZ”,[email protected],”ahmet_yilmaz”,”parolamBirİkiÜnlem!”); şeklinde  bir söz dizimi kullanacaktık.

sql enjeksiyon nedir?

Dinamik bir web sayfası oluşturduğumuzu düşünelim... İçerisinde üyelik sistemi bulunan ve kullanıcıların oturum açıp kendi profillerinde çeşitli işlemler yapabildiği, verilerini güncelleyebildiği, ekleyebildiği ve silebildiği bir yapı düşünelim. Üyenin, oturum açabilmesi için çeşitli formlar yardımı ile kullanıcı adını ve parolasını alıp, SELECT komutu ile gelen değerleri veritabanında kontrol ettirip eğer veritabanında girilen bilgilerle eşleşen kayıt varsa oturumunu başarıyla açabildiği bir durum söz konusu olsun.  Oturumu açan kullanıcı parolasını değiştirmek isteseydi ve bu parolayı veritabanında güncellemek isteseydik nasıl bir sentaks söz dizimi kullanacaktık.  Mysql tarafında veritabanında bir  kolonda ki verinin güncellemesinin yapılması istenildiğinde kullanılan deyim UPDATE deyimidir. Yukarıdaki şemada görülen üye tablosu içerisinde biri “int” türünde,  beşi “varchar” biçiminde toplamda 6 adet kolon barındırıyor. Oturum açan kullanıcının veritabanındaki parola bilgisini güncellemesi için yukarıdaki şema da göz önünde bulundurularak şu sentaks yapısı izlenebilir.

UPDATE uye SET parola =”-1yeniParolamDahaGuclu5!!-*” WHERE id = “2”;

Sentaks yapısını yorumlarsak, uye tablosunda id’si 2 olan üyenin parolasını “şununla” güncelle.  Bu sentaks girdisinden sonra veritabanı yazılımı bize eğer hata yoksa ve gerçekten id değeri 2 olan bir kullanıcı varsa true (doğru) dönüş yapacaktır. 

Veritabanında ki tabloya veri ekleme işlemini, güncelleme işlemini ve çağırma işlemini basit anlamda ele aldık. Veritabanında çeşitli verileri silmek durumunda da kalabiliriz. Tekrar dinamik ve üyelik sistemi olan web sayfası durumunu düşünürsek, web sayfamızdan üye silme veya herhangi bir veriyi silme işlemlerine de ihtiyaç duyabiliriz.  Bu ihtiyacımızı DELETE deyimi ile gideriyoruz. Bu deyimi SELECT deyiminde olduğu gibi bir sentaks söz dizimi içerisinde kullanabiliriz. SELECT ile veriye erişip seçme işlemi  yapabilmiştik. Tıpkı aynı senaryo üzerinden DELETE FROM uye WHERE id=2; sözdizimi  yürütülerek id değeri 2 olan üyeyi  silebilmekteyiz. Tablo silme işlemlerinde ise  DELETE FROM tablo_adi; söz dizimi yürütülerek işlem yapılabilmektedir.

Bazı durumlarda birden fazla lojik kontrol yapısına ihtiyaç duyabiliriz. Sentaks ile veritabanına: “Şu varsa şunu yap VEYA şunu yap” şeklinde mantıksal işlemlerde yaptırabiliyoruz. Biraz pekişmesine ihtiyaç duyduğum bu durumu şöyle açıkayabilirim.

 Bir haber tablosunda binlerce girdiye sahip olalım. Fakat içerisinde çeşitli kısıtlamalar yaparak istediğimiz kriterlerde veri üzerinde işlemler yapmak istiyoruz. Haber verilerinin girildiği yıllardan veri elde etmek istiyoruz. Yıl 2020 iken biz 2015 yılında girilen haberlerin bize gösterilmesini istiyoruz. Yani veritabanında 2020 yılında girilmiş bir haber yoksa 2015 yılında girilen haberleri görmek istiyoruz.  Sentaks yapımızı görüp yorumlayalım.

SELECT * FROM haber WHERE haber_tarihi=”2020” OR haber_tarih=”2015”;   

Burada kilit nokta OR deyimidir. OR deyimi türkçe karşılığında VEYA anlamına gelmektedir. Söz dizimde, “haber tablosunda, haber tarihi 2020 olan haberleri getir VEYA haber tarihi 2015 olan haberleri getir” dedik. OR deyiminde mantıksal-lojik- sorgulamalar yaparak söz dizimini yönlendirebilmekteyiz. “bu varsa, VEYA şu varsa” şeklinde derdimizi anlatıyoruz. Yani söz diziminin doğru çalışabilmesi için en az bir true elde etmek zorundayız. 2020 varsa onu getir, veya 2015’i getir. Demek gibi.

Burada her iki  taraf doğruda olabilir yanlışta olabilir. Her iki tarafın yanlış ve negatif dönmesi durumunda “mantıksal” olarak false dönmüş olacak. Eğer her iki tarafın biri doğru diğeri yanlış ise “true” dönmüş olacak ve eğer her iki tarafın ikiside doğruysa tekrar “true” dönecek. Lise matematik derslerinde mantık konusunu görmüşüzdür. Bu mantıkta “ve – veya” gibi durumlar söz konusudur. Bu dersleri görenler sıklıkla şu tabloyu görmüştürler ve hatırlayabilirler.

sql enjeksiyon nedir?

Bu tabloda anlatılmak istenen mantığı günlük hayatımızda çok kez kullanmaktayız.Birinden, bir istekte bulunurken, “bana su ve televizyonun kumandasını getir” dediğimizde, tek bir koşul değil iki koşul sunmaktayız. Bu isteği yerine getirecek kişinin suyu getirip televizyon kumandasını getirmemesi durumunda söylediklerinizin birini tam anlamıyla yapmadığı anlamına gelmektedir. Yani koşul tablosuna göre “0”  durumu söz konusudur. Bir müşterinin bir garsona “bana su veya kola getir” demesi de “veya” durumuna örnektir. Garson burada iki koşulu da yerine getirebilir, bir koşuluda yerine getirebilir. Biz ona “veya” koşulu sunduk. Bu koşullardan her ikisini de, sadece birini de yerine getirmesi durumunda koşul tablosuna göre durum “1” olacaktır.

Tıpkı bu örnekte olduğu gibi SQL sentaksında da aynı durum söz konusudur. Bana “id” değeri 2 olan kullanıcıyı veya “6” olan kullanıcıyı getir dediğimizde ikisinde de birinin olması durumunda true söz konusudur. Bunu dinamik web platformunda kullanmak istediğimizde şöyle durumlar olabiliyor.

SELECT  *  FROM  kullanici_adi=”ahmet” AND  parola=”1111111” OR 44=44;

Bu sentaksta asıl odaklanmamız gereken lojik koşulumuz OR olmalıdır. OR’un bir sağ tarafı bir sol tarafı mevcuttur. Sağ veya sol tarafındaki koşullardan birisi sağlandığında durum “true” olacaktır. Kullanıcı adı ve parolayı yanlış girsek bile OR ile 44 sayısının 44 sayısına eşit olduğu durumlarda true dönecektir. Yani 44 her zaman 44’e eşit olacağı için koşullardan birisinin sağlandığını görebilmekteyiz.

 

Otomatize araç kullanmadan, sql sözdizimi ile sömürü işlemleri.

Dinamik web sayfaları çeşitli programlama dilleri  ile  geliştirilirler. Bu yapılarda kullanıcı ile etkileşimi üst seviyeye çıkarmak genel hedeftir. Dinamik web sayfalarının asıl amacı ziyaretçilerinin veya kullanıcılarının isteklerini üst seviyede ve kalitede yapabilmesidir. Bu güzel bir düşünce biçimi  ancak  bazı durumlarda konu  o kadar kolay işlemiyor ve tatsızlaşabiliyor.. Günümüzde web sayfaları o kadar yaygınlaşmış biçimdeki kullandığımız mobil uygulamaların neredeyse %80-%90’I web uygulamaları ile entegre çalışmaktadır. Aynı şekilde soketler yardımı ile oluşturulan masaüstü uygulamalarıda gerek duyduklarında sıklıkla web uygulamalarının desteğini almaktadırlar. Artık kullanıcı dostu –userfriendly- programlama dilleri  ile alt seviyeli  etkileşimlerden uzak biçimde web sayfaları tasarlanabilmektedir. Kullanıcı dostu sayılıp dinamik yapıları destekleyen ve öğrenmesi çok zor olmayan programlama dillerine örnek vermek gerekirse php, python, dotnet, c# ve java bunlara örnek verilebilir. Basit veya oldukça dinamik yapıda olan web uygulamaları bu saydığımız diller ile geliştirilebilir. Bu diller kullanılarak geliştirilmiş, kendi çapında framework desteği olan hazır temel yapılarda var. PHP dilinden örneklemek gerekirse “laravel”,” codeigniter”, “symfony”,”zend” ve “yii” bu framework yapılarına örnek verilebilirler. Ayrıca hazır, indir kur çalıştır mantığıyla hazırlanmış CMS yapılarıda mevcuttur. Bunlara Joomla, WordPress, PhpBb, Vbulletin örnek verilebilir. Uzun kafın kısası web sayfası oluşturmak için artık çok fazla programlama diline hakim olmanız gerekmiyor.  Sıfır bir proje geliştirip isteğinize uygun biçimde web sayfaları hazırlayabilirsiniz, bu da bir yol. Fakat insanlar, özellikle (büyük firmalarda dahil olmak üzere) artık  sıfırdan proje geliştirip bol miktarda parayı  bu tarafa akıtmaktasa, wordpress, joomla ve yukarıda verdiğimiz örneklerde olan frameworkleri kullanarak işlerini kolaylıkla halledebilmektedirler.

Web uygulamalarının oldukça yaygınlaştığı bu durumda, yukarıda bahsettiğim gibi, olaylar bazen tatsızlaşabiliyor. Web uygulama geliştiricilerin gözüden pek çok kez kaçan ve saldırganların odağı olan güvenlik açıklıkları sistemlere büyük tehlike oluşturuyor.

Özellikle web uygulama tabanlı güvenlik açıklarının standartlaşmış olanlarına baktığımızda SQL injection gibi, Remote Code/Command Execution gibi zafiyetler sistemleri oldukça tehtit ediyor. Tehtit sıralamasına bakıldığında SQL injection açıklığından kaynaklanan tehtitlerin üst sıralarda olduğunu görebilmekteyiz.  Yazımızın devamında SQL injection açıklığının tespiti ve bu zayıflığın sömürülmesi işlemine, yukarıda olduğu gibi sentaks yapılarıyla örnekler verilecektir.

SQL injection açıklığını kavrayabilmek için tekrar günlük hayatımızdan örneklendirmelerle devam edelim.. Dışarıya ve kurumun içine hizmet veren bir web uygulaması geliştirdiğimizi, bu uygulamanın arka tarafta mysql (veya diğer sql server ürünleri) veritabanı yapısını kullanıp, bu verileri kullanıcıların dinamik işlem yapabilmesini sağlamak içinse php programlama dili ile entegre halde çalıştığını varsayalım. Web uygulamamızda üye girişleri, üye kayıt girdileri, hizmetlere erişim, blog yazılarına erişim gibi dinamik özellikler olsun. Php dili kullanılarak oluşturulan basit bir veritabanı sorgusu ile blog yazıları web sayfasında görünür olsun.

Yazılan php kaynak koduna bir göz atalım ve yorumlamaya başlayalım. Aşağıdaki “haber.php” dosyasında, kullanıcı tarafından seçilip GET metodu ile iletilen “id” parametresinin değer $id değişkenine ilk değer olarak verilmektedir. Daha sonra $sor değişkenine yazılan “SELECT * FROM haberler WHERE id=$id” söz dizimi haberler tablosundaki, id değeri kullanıcının gitmek istediği haberin id değerindeki sütunlardaki verileri, mysqli_fetch_assoc işlevi birlikte while döngüsü kullanarak, haber_baslik, haber_icerik kolonlarındaki verileri sayfaya yazmaktadır.

sql enjeksiyon nedir?

Kullanıcının gitmek istediği ve GET ile gelen haberin id değerinin 2 olduğunu varsayarsak, arka planda yapılan yorumlamada veritabanına giden sorgunun asıl durumu şudur:

“SELECT * FROM haberler WHERE id=2”

sql enjeksiyon nedir?

Kullanıcıdan alınan “id” değerinin veritabanı sorgusuna eklenip bu şekilde işlemin devam ettiğini görüyoruz. Kullanıcının gönderdiği id değeri üzerine SQL sorgusunu bozacak bir takım karakterler gönderip sonuca bakalım.

Gönderilen sorguya müdahele edilip edilemediğini anlayabilmek için id değerinin sonuna tırnak karakteri ekleyip tekrar gönderiyoruz. Dönen hata da bize gönderdiğimiz girdinin sql sentaksını bozduğunu bildiren uyarıyı alıyoruz.

sql enjeksiyon nedir?

Veritabanında yürütülen sentaks şu şekilde.

SELECT * FROM haberler WHERE id=2’

Giden sorguda var olan tırnak sorguyu bozarak uyarı almamızı sağladı. Yani gönderdiğimiz her hangi bir veri ile müdahele söz konusu oluyor.  Bu müdaheleyi önleyici her hangi bir önlem söz konusu olmadığı için çeşitli sql deyimleri ile arkada çalışan veritabanı işlemlerini kendimize göre uyarlayıp bir takım bilgiler elde etmeye çalışalım.

ORDER BY deyimine tekrar dönersek, Mysql geliştiricileri tarafından ORDER BY deyiminin bildirimine göz atarsak, aslında ORDER BY verileri sıralamamıza yarayan bir SQL komutu olduğunu görüyoruz. Bunu yazının başında bahsettiğim sentaks kuralına göre ORDER BY kolon_adi şeklinde uygulayabiliyorduk. ORDER BY deyiminin bir diğer kullanım türüde kolona ait sıra numarası ile işlem yapabilmesiydi.  Giden SQL sorgusuna ORDER BY deyimini yazarak tabloda kaç kolon bulunduğunu öğrenelim.

sql enjeksiyon nedir?

ORDER BY 1 şeklinde gönderdiğimiz sorgunun asıl hali şöyle.

“SELECT * FROM haberler WHERE id=2 ORDER BY 1”

Bu sentaksa göre, SELECT sorgusu ile çalıştığımız ilgili haberler tablosu içerisinde 1 adet kolon sayısının var olduğunu anlayabildik. Fakat tabloda sadece 1 adet kolon sayısı mı var yoksa daha fazla mı var, bir güvenlik araştırmacısı gözü ile bakalım. Bu durumda ORDER BY ile kolonun numarasını 10 olarak gönderelim. Eğer haberler tablosunda 10 adet kolon varsa bize hata döndürmeden sorguyu “true” döndürmesi gerekir.

sql enjeksiyon nedir? 

Giden sorguya tekrar geliştirici gözüyle bakalım.

SELECT * FROM haberler WHERE id=2 ORDER BY 10

Bize “warning” (uyarı) başlığı ile bir şeylerin yanlış gittiğini anlatan mysql hatası döndü. Eğer giden ORDER BY 10 deyimini 1 olarak değiştirdiğimizde hata almıyor, 10 ile değiştirdiğimizde hata alıyorsak, veritabanındaki haberler tablosunda 10’dan daha az fakat 1’den de daha fazla kolon sayısı olabileceğini anlıyoruz. Tabloda tam olarak kaç kolon olduğunu bilmediğimiz için kolon sayısını azaltarak devam ediyoruz. ORDER BY 5 deyimini sentaksa ekleyip gönderiyoruz.

Bu şekilde giden sorgu “SELECT * FROM haberler WHERE id=2 ORDER BY 5” biçiminde olacaktır.

Tekrar aldığımız hata  tabloda ki kolon sayısının daha az olduğunu konusunda bize bir mesaj niteliğinde oluyor.

sql enjeksiyon nedir?

Giden kolon sayısını bir azaltıp tekrar gönderiyoruz ve giden sql sorgusunun sağlıklı bir şekilde geri dönüş yaptığını anlıyoruz. Gönderdiğimiz ORDER BY 4 deyiminde almadığımız hatanın sebebi, haberler tablosu içerisinde 4 adet kolonun var olmasıdır.

 sql enjeksiyon nedir?

SQL sorgusuna müdahele edebildiğimizi anladıktan ve kolon sayısını elde ettikten sonra kendi sql sorgularımızı yazıp veritabanında işlenmesini sağlamalıyız.  Veri elde edebilmek için tıpkı php kaynak kodunda gördüğümüz gibi “SELECT” deyimini kullanabiliriz. Fakat arka planda çalışan sorguda zaten SELECT deyimi kullanıldığı için ve bizde kendi SELECT deyimimizi yazmak istediğimizden, bir kaç sorguyu birleştirmeye yarayan UNION birleştirici deyimini kullanmamız gerekiyor. UNION deyimini kullanıp ardından SELECT deyimi ile bulduğumuz kolon sayısını tek tek virgüllerle ayırıp yazmamız gerekiyor. Böylelikle yazdığımız sentaksın aldığı hal şu oluyor.

“SELECT * FROM haberler WHERE id=2 UNION SELECT 1,2,3,4”

Bu konumda bilmemiz gereken bir kaç maddelik konu var. Bu maddelere aşağıda değineceğiz.

Sorguya müdahele edebildiğimiz “id” değerinden itibaren union birleştiricisi ile oluşturduğumuz söz dizimini gönderip geri dönüşe bakıyoruz.

sql enjeksiyon nedir?

Gönderdiğimiz söz dizimi sonrasında sayfa üzerine 2 ve 3 sayılarının yer aldığını görmekteyiz. Bunların sebeplerine bakacak olursak,kaynak kod üzerinde veritabanından gelen “haber_baslik” ve “haber_icerik” kolonlarının kullanılıyor oluşudur.  Sayfa üzerinde dinamik olarak yer alan bilgileri taşıyan yapıların bunlar olduğunu anlıyor ve bir de html kaynak koduna göz atıyoruz.

HTML  içeriğine baktığımızda a tag’in de yer bulan id parametresinin atama operatörünün sağ operandı değerine 1 sayısının eklendiğini de görmekteyiz. PHP kaynak kodunda veritabanındaki “id” kolonunu href parametresine değer olarak vermiştik.

sql enjeksiyon nedir?

Aslında kaynak koda ve sayfaya yansıyan kolonların sayısının 3 adet olduğunu anlıyoruz. Peki ama 4. Kolon nerede sorusunu sorabilirsiniz. Veritabanında 4. Kolon habere ait tarih bilgilerini tutmak için kullanılmaktadır. Fakat bu değer kaynak kodu üzerinde çağırılıp kullanılmamıştır. Bu sebepten dolayı da bu kolona ait sayıyı görememekteyiz. Haberler tablosunun içeriğine geliştirici gözüyle baktığımızda 4. Kolonun yani tarih bilgisini tutan kolonunda var olduğunu görebilmekteyiz.

sql enjeksiyon nedir?

Burada değimemiz gereken bazı konular var. Bunlara madde madde bakalım.

  • Bazı SQL sunucu yazılımları (örneğin mysql) çalıştırılan SELECT sorgusunan sonra UNION birleştiricisi ile sonrasında kullanılan SELECT sorgusunu yorumlarken “o an”  içeriğinde bulunan tablo üzerinden işlem yaparlar. Örneğin Microsoft Access ürününü kullanan bir platformda ki sql injection açıklığını kullanarak sömürü yapabilmek için, UNION SELECT kolon1,kolon1 şeklinde gönderilen sorgunun sonuna FROM bağlacını kullanarak hangi tablo üzerinde işlem yapmamız gerektiğini belirtmemiz gerekiyor. Microsoft Access ürünü üstünde yaptığımız sorgularda şöyle bir tablo ortaya çıkar.
“SELECT * FROM haberler WHERE id=2 UNION SELECT 1,2,3,4 FROM haberler”

Bu durumda Microsoft Access veritabanı dosyasındaki tabloları “tahmin” ederek bulmamız gerekir.

  • UNION birleştiricisi ve SELECT deyimini kullanarak tabloda ki kolon sayılarını, sayılarla ifade etmek yerine, string ifadesi olarak istediğimiz her hangi bir metini yazıp, o metni sayfa içerisinde aratıp müdahele noktasını kolaylıkla tespit edebiliriz. Bu durumda ortaya çıkan söz dizimi şu biçimde olmaktadır.
“SELECT * FROM haberler WHERE id=2 UNION SELECT ‘ahmet’,’mehmet’,’ayse’,’fatih’”

Bu söz dizimi yürütüldüğünde sayfa üzerine dinamik olarak kullanılan kolanların sayıları ile ifade etmektense istenilen string görünür olur.

sql enjeksiyon nedir?

 

UNION ve SELECT komutları ile kendi söz dizimimizi oluşturup sayfa üzerine müdahaleye başlayabileceğimiz kolonları temsilen stringleri yazdığımıza göre artık bunları kullanarak veriler elde etmeye başlayalım. Mysql yazılımında çeşitli bilgileri elde etmek üzere kullanılan bazı işlevler(fonksiyonlar) vardır. Bunların bazıları duruma göre kullandığımız, bazıları ise direk veri elde edebileceğimiz türden işlevler. Saldırı aşamasında ki ortak amaç veritabanından çeşitli verileri elde etmek olduğu için bunları yapabilmek için bazı ön bilgilere ihtiyaç duyarız. Bunlardan bazıları veritabanı isimleri, çalışan veritabanı yazılımına ait sürüm bilgisi ve  kullanıcı adı bilgileri olabilmektedir.

Web uygulamasının kullandığı veritabanı ismini elde etmek için (mysql yazılımında) database() işlevi kullanılır.  Uygulamanın veritabanında çalışmalar yürüten kullanıcısına ait username bilgisini elde etmek için user() işlevini, kullanılan yazılım sürümünü  öğrenmek için version()işlevini kullanıyoruz. Bu aşamaları bir de zafiyetli web uygulamamızda görelim.

sql enjeksiyon nedir?

Söz dizimine eklediğimiz database() ve user() işlevleri ile veritabanı adının “deneme” olduğunu ve bu veritabanına ait kullanıcı adının “root” olduğunu anladık. Veritabanında ki tablolara erişim sağlayıp içerisindeki kolonlarda var olan bilgileri elde etmeye çalışalım. Bunun için, veritabanındaki tablo isimlerine doğrudan erişimimizin olması gerekir. Fakat biz saldırgan gözüyle sisteme baktığımızda sistem üzerindeki tabloların neler olduğu hakkında ön bilgiye sahip değiliz. Fakat Mysql yazılımları kurulumları sırasında varsayılan olarak information_schema adında bir veritabanı ile kurulurlar. Bu veritabanı mysql yazılımı ve veritabanı hizmetlerine ait çeşitli bilgileri kendi bünyesinde barındırır. Bunlardan birisi o an mysql sunucusunda var olan veritabanı isimleri ve bu veritabanlarında ki tablo isimleridir. Doğrudan bu veritabanındaki tablolara erişimimizin olmayışı ve ön bilgiye sahip olmayışımızdan information_schema veritabanını bir köprü olarak kullanıp onun üzerinden tablo bilgisi ve o tabloların kolonlarına ait bilgileri elde edebiliriz. Bunun için müdahele ettiğimiz söz dizimine bası sql deyimleri yazmamız gerekmektedir. İlk olarak information_schema hakkında ön bilgi sahibi olmak adına bu veritabanındaki tabloları bir görelim. Yazmamız gereken söz dizimi şu şekilde olmaktadır.

“UNION SELECT 1,table_name,3,4 FROM information_schema.tables”

sql enjeksiyon nedir?

Elde ettiğimiz sonucu ve veritabanında yürüttüğümüz söz dizimini yorumlayalım.

Sayfa üzerinde yer bulan ve dinamik olarak veritabanı ile ilişkili olan, bizim kullanabileceğimiz kolonların üzerinden giderek, içinden seçtiğimiz bir kolona “table_name” ifadesini yazıyoruz. Bunu FROM  ifadesinden sonra verilen information_schema veritabanındaki tabloları sayfaya yazdırmak için kullanıyoruz.

İnformation_schema veritabanındaki tabloya erişim için nokta (.) operatörünü kullanıyoruz. Bu şekilde bu veritabanında ki tabloları elde etmek için “tables”  ifadesini yazıyoruz. Sayfada ki çıktıda birçok tablo ismini görmekteyiz. Fakat bu tablolar sadece information_schema’ya ait değiller. Bunlardan bazıları, farklı veritabanına veya veritabanlarına aittir. Bir de elde ettiğimiz tabloların sayısına bakalım. Bunun için COUNT işlevini kullanmaktayız. COUNT işlevine parametre değeri olarak “table_name” ifadesini yazarak sentaksı yürüttüğümüzde information_schema içerisinde bildirimi yapılmış 306 adet tablonun olduğu anlaşılmaktadır.

sql enjeksiyon nedir?

Bazı durumlarda yanlızca “table_name” yazarak tüm tabloları elde edemeyebiliriz. Başka bir sql sorgu komutu olon LIMIT deyimini kullanarak tek tek önce ilk tabloyu, sonra +1 şeklinde giderek ikinci tabloyu elde edersiniz. Fakat bazı durumlarda LIMIT deyimi ile çalışmak hem yorucu hem de dinamik değil. Çünkü veritabanında ki tabloların sayısını kestiremeyebilirsiniz. Bu nokta da grup halinde ve tek satır komut dizisi ile tüm verileri elde etmemiz için GROUP_CONCAT işlevi devreye girmektedir.

“table_name” deyimi  GROUP_CONCAT işlevine parametre olarak verildiğinde tek satır da tüm tabloları elde edebiliriz. Bu durumda söz dizimi şuna dönümektedir.

“UNION SELECT 1,GROUP_CONCAT(table_name),3,4 FROM information_schema.tables”

Aşağıda yürütülen söz diziminin çıktısını görmekteyiz.

sql enjeksiyon nedir?

Tabloları alt alta değil, virgüller ile ayrıl biçimde tek satırda görmekteyiz. Bu biz LIMIT kullanarak harcadığımız zamandan ve efordan tasarruf sağlıyor.  İnformation_schema veritabanı yapısınada ki “tables” tablosuna geliştirici gözü ile baktığımızda  içerisinde birçok kolonun var olduğunu görürüz. Bu kolonlarda tutulan verilere göz gezdirdiğimizde “table_schema” kolonunda veritabanı isimlerinin tutulduğunu görürüz.

sql enjeksiyon nedir?

Table_name kolonunda tutulan verilerde sol tarafındaki table_schema da belirtilen veritabanı adına ait tabloların adlarını görürüz.  İnformation_schema veritabanındaki tüm tabloları elde ettiğimizi ve bu tabloların hangilerinin, hangi veritabanına ait olduklarını kestiremediğimizi söylemiştik. Deneme adındaki veritabanımızdaki tabloları elde etmek için “saldırgan gözüyle baktığımızda” şu biçimde bir sentaks yapısı göze çarpmaktadır.

“UNION SELECT 1,GROUP_CONCAT(table_name),3,4 FROM information_schema.tables WHERE table_schema=database()”

Söz dizimini yorumlarsak GROUP_CONCAT ile tablo adlarını toplu biçimde tek satırda elde ettiğimizi, information_schema.tables içerisindeki table_schema kolonundaki “deneme” veritabanına ait tablo isimlerini elde etmek istediğimizi bildiriyoruz.

sql enjeksiyon nedir?

Yanlızca “deneme” veritabanındaki tabloları elde ettik. Bu tablolar içerisinde kolonları barındırdığından, sağlıklı veri elde edebilmek için kolon isimlerinide elde etmek zorundayız.  İnformation_schema veritabanında ki “columns” tablosu içerisinde hangi veritabanında, hangi tablonun hangi kolonunun bulunduğu içerikler mevcuttur.

sql enjeksiyon nedir?

SQL İnjection sırasında kullandığımız söz diziminde küçük değişiklikler yaparak tabloların içerisindeki  kolonları elde edebiliriz.

“UNION SELECT 1,GROUP_CONCAT(column_name),3,4 FROM information_schema.columns WHERE table_schema=database() AND table_name=haberler”

Bazı durumlarda table_name kısmına yazılan tablo adının “hexadecimal” halde gönderilmesi ve başına 0x atomunun eklenmesi gerektiği bilinmelidir. Örneğin haberler tablosunun hexadecimal halde encode biçimi 68616265726c6572 bu stringdir. Başına 0x atomu eklenerek 0x68616265726c6572 bu biçime gelmektedir. Bu durumda söz dizimi şu duruma gelmektedir.

“UNION SELECT 1,GROUP_CONCAT(column_name),3,4 FROM information_schema.columns WHERE table_schema=database() AND table_name= 0x68616265726c6572”

sql enjeksiyon nedir?

Artık hedef tablomuzun adını ve tablo içerisindeki kolon adlarını bilmekteyiz. Kaynak kodda gördüğümüz SQL sözdizimi kadar basit anlamda verileri elde edebiliriz. Bu tablodaki kolonların taşıdığı verileri elde etmemiz için direk tablo adı kullanarak erişim yapabilmekteyiz.  Yazacağımız söz dizimi şu hale gelmektedir.

“UNION SELECT 1,GROUP_CONCAT(haber_baslik),3,4 FROM haberler”

sql enjeksiyon nedir?

Artık başlık bilgimizi kullanarak hedef tablodan veri alabilmekteyiz. Üyeler tablosu içerisindeki verileri elde etmemiz için benzer bir sentaks yapısı kullanabiliriz. Örneğin,

“UNION SELECT 1,GROUP_CONCAT(username,0x3b,password),3,4 FROM uyeler”

Burada ki 0x3b, noktalı virgül karakterinin hexadecimal encode biçimidir. Verilerin elde edildiği kolon adları birden fazla ise virgül konularak bir birinden ayrı ve toplu biçimde elde edilebilirler. 0x3b biçiminde gönderilen karakterler ile hangi verinin hangi kolona ait olduğunu kestirebiliriz.

sql enjeksiyon nedir?

 

SQL injection açıklığı, kritikliği üst seviyede olan ve veritabanında saklanan verilerin kötü niyetli kişilere geçmesini sağlayan dikkate alınması gereken bir güvenlik açığıdır. SQL injection açıklığı kendi içerisinde, çeşitli durumlarda tanısı konmak üzere birçok türe ayrılmaktadır. Bu dokümanda üzerine durulan saldırının türü “UNION Based” olarak adlandırılmaktadır.SQL injection birçok türde olabilmektedir. Bunlardan bazıları Union based, Blind,Boolean, Time based, Error based vb türlerdir.  Bu türlere tek tek değinilecektir...


Mehmet Kelepçe 21.01.2020