SQL enjeksiyonu

SQL enjeksiyonu, veri tabanına dayalı uygulamalara saldırmak için kullanılan bir saldırı tekniğidir; burada saldırgan SQL dili özelliklerinden faydalanarak standart uygulama ekranındaki ilgili alana yeni SQL ifadeleri ekler. (Örneğin saldırgan, veritabanı içeriğini kendisine aktarabilir). SQL enjeksiyonu, uygulamaların yazılımları içindeki bir güvenlik açığından faydalanır. Örneğin, uygulamanın kullanıcı giriş bilgileri beklediği kısma SQL ifadeleri gömülür. Eğer gelen verinin içeriği uygulama içerisinde filtrelenmiyorsa veya hatalı şekilde filtreleniyorsa, uygulamanın içine gömülmüş olan kodla beraber hiçbir hata vermeden çalıştığı görülür. SQL enjeksiyonu, çoğunlukla web siteleri için kullanılan bir saldırı türü olarak bilinse de SQL veri tabanına dayalı tüm uygulamalarda gerçekleştirilebilir. SQL enjeksiyon saldırıları, saldırganların sistemdeki kullanıcılardan birinin bilgileriyle giriş yapmasına, mevcut verilere müdahale etmesine, bazı işlemleri iptal etmesine veya değiştirmesine, veritabanındaki tüm verileri ifşa etmesine, veritabanındaki tüm verileri yok etmesine veya veritabanı sunucusunda sistem yöneticisi olmasına olanak sağlar. SQL enjeksiyonu, SQL alt dilini kullanan PHP, ASPX gibi birçok programlama dili üzerinde görülebilmektedir. Bu saldırı tekniği, SQL dili kullanılan sistemlerde genellikle GET ve POST verileri gönderilip alınırken yapılmayan filtrelemeler sebebiyle ortaya çıkar. 2012'de yapılan bir araştırmada, bir web uygulamasının ayda ortalama 4 saldırı aldığı ve perakendecilerin diğer endüstrilerden iki kat fazla saldırıya maruz kaldığı görülmüştür.
Bu maddedeki bilgilerin doğrulanabilmesi için ek kaynaklar gerekli. (Şubat 2022) (Bu şablonun nasıl ve ne zaman kaldırılması gerektiğini öğrenin) |

SQL enjeksiyonu, veri tabanına dayalı uygulamalara saldırmak için kullanılan bir saldırı tekniğidir; burada saldırgan SQL dili özelliklerinden faydalanarak standart uygulama ekranındaki ilgili alana yeni SQL ifadeleri ekler. (Örneğin saldırgan, veritabanı içeriğini kendisine aktarabilir).[1] SQL enjeksiyonu, uygulamaların yazılımları içindeki bir güvenlik açığından faydalanır. Örneğin, uygulamanın kullanıcı giriş bilgileri beklediği kısma SQL ifadeleri gömülür. Eğer gelen verinin içeriği uygulama içerisinde filtrelenmiyorsa veya hatalı şekilde filtreleniyorsa, uygulamanın içine gömülmüş olan kodla beraber hiçbir hata vermeden çalıştığı görülür. SQL enjeksiyonu, çoğunlukla web siteleri için kullanılan bir saldırı türü olarak bilinse de SQL veri tabanına dayalı tüm uygulamalarda gerçekleştirilebilir.
SQL enjeksiyon saldırıları, saldırganların sistemdeki kullanıcılardan birinin bilgileriyle giriş yapmasına, mevcut verilere müdahale etmesine, bazı işlemleri iptal etmesine veya değiştirmesine, veritabanındaki tüm verileri ifşa etmesine, veritabanındaki tüm verileri yok etmesine veya veritabanı sunucusunda sistem yöneticisi olmasına olanak sağlar.
SQL enjeksiyonu, SQL alt dilini kullanan PHP, ASPX gibi birçok programlama dili üzerinde görülebilmektedir. Bu saldırı tekniği, SQL dili kullanılan sistemlerde genellikle GET ve POST verileri gönderilip alınırken yapılmayan filtrelemeler sebebiyle ortaya çıkar.
2012'de yapılan bir araştırmada, bir web uygulamasının ayda ortalama 4 saldırı aldığı ve perakendecilerin diğer endüstrilerden iki kat fazla saldırıya maruz kaldığı görülmüştür.[2]
Tarih
[değiştir | kaynağı değiştir]SQL enjeksiyonu, 1998 yılı civarında tartışılmaya başlanmıştır.[3] Örneğin, 1998'de Phrack dergisinde yayımlanan bir makalede SQL enjeksiyonundan söz edilmiştir.[4]
Form
[değiştir | kaynağı değiştir]Açık Web Uygulaması Güvenlik Projesi (AWUGP)[5] verilerine göre, SQL enjeksiyonunun (SQLi) 2007-2010 yılları arasında web uygulamalarında en fazla görülen 10 güvenlik açığından biri olduğu belirtilmiştir.[6] 2013'te ise yine AWUGP kapsamında, SQLi'ın web uygulamalarına en fazla yapılan saldırı olduğu kabul edilmiştir.[7] SQL enjeksiyonunun dört ana alt sınıfı vardır:
- Klasik SQLi
- Körleme SQL enjeksiyonu
- Veritabanı Yönetim Sistemi Özel SQL enjeksiyonu
- Birleşik (Compounded) SQL enjeksiyonu:
- SQL enjeksiyonu + yetersiz kimlik doğrulama[8]
- SQL enjeksiyonu + DDoS saldırıları[9]
- SQL enjeksiyonu + DNS korsanlığı[10]
- SQL enjeksiyonu + XSS[11]
Storm Worm saldırısı, birleşik (compounded) SQLi saldırılarına bir örnektir.[12]
Bu sınıflandırma, 2010'a kadar olan SQLi saldırıları için geçerlidir. Yeni gelişmeler için sınıflandırmalar yapım aşamasındadır.[13]
Teknik uygulamaları
[değiştir | kaynağı değiştir]Kaçış (Escape) karakterlerinin yanlış filtrelenmesi
[değiştir | kaynağı değiştir]SQLi'ın bu türü, kullanıcıdan gelen veri kaçış (escape) karakterlerine göre filtrelenmediği zaman uygulamaya kullanıcı girişinden yeni SQL ifadeleri eklenmesiyle oluşur. Eklenen SQL ifadeleri, son kullanıcının veritabanını istediği şekilde manipüle etmesine neden olur.
Aşağıdaki kod satırı bu güvenlik açığını göstermektedir:
sorgu = "SELECT * FROM kullanicilar WHERE isim =' " + kullaniciAdi + " ';"
|
Yukarıdaki SQL sorgusu girilen kullanıcı adı bilgisine ait tüm verileri, kullanıcı tablosundan çekecek şekilde tasarlanmıştır. Sistem kullanıcı adı bekliyorken, kötü niyetli bir kullanıcı tarafından sisteme zarar verecek SQL ifadeleri yazılabilir. Örneğin, "kullaniciAdi" değişkeninde aşağıdaki gibi bir düzenleme yapılabilir:
' or '1'='1
Bu girdi, SQL ifadesinin aşağıdaki şekilde işlenmesine neden olur:
sorgu = "SELECT * FROM kullanicilar WHERE isim =' " + kullaniciAdi ' or '1' = '1 + " ';"
|
Sorgunun geri kalanını engellemek için yorum satırı karakterleri kullanılır. (Aşağıda üç farklı SQL yorum satırı karakteri gösterilmiştir.[14]). Üç satırın sonunda da bir boşluk bulunmaktadır.
' or '1'='1' --
' or '1'='1' ({
' or '1'='1' /*
Saldırgan bu SQL ifadelerini uygulamaya kullanıcı girişi olarak girerse, uygulama tabanında çalışacak sorgu aşağıdaki şekilde olur:
SELECT * FROM kullanicilar WHERE kullaniciAdi ='' or '1' = '1 + " ';
|
"SELECT * FROM kullanicilar WHERE isim ='' or '1' = '1 + " ';"
"SELECT * FROM kullanicilar WHERE isim = '' OR '1'='1' -- ';
SELECT * FROM kullanicilar WHERE kullaniciAdi = '' OR '1'='1' -- ';
|
kullaniciAdi verisi ne olursa olsun '1'='1' koşulu sağlanacağı için ve aradaki işlemin OR olmasından dolayı sorgu sonucu her zaman olumlu olacaktır. Yorum satırı karakterlerinden sonra gelen tüm karakterler yorum niteliği kazanacaktır ve onların bir önemi kalmayacaktır.
Aşağıdaki SQL ifadesinde "kullaniciAdi" alanına girilen değer, kullanıcılar tablosunun silinmesine ve kullanıcı bilgileri tablosundaki tüm verilerin ifşa edilmesine neden olur.
a';DROP TABLE kullanicilar; SELECT * FROM kullaniciBilgileri WHERE 't' = 't'
|
Bu girdi SQL ifadesinin aşağıdaki şekilde işlenmesine neden olur:
SELECT * FROM kullanicilar WHERE kullaniciAdi = 'a'; DROP TABLE kullanicilar; SELECT * FROM kullaniciBilgileri WHERE 't' = 't';
|
Çoğu SQL sunucusu, bir çağrı ile birden fazla SQL ifadesinin yürütülmesine izin verirken, PHP'nin mysql_query() fonksiyonu gibi bazı SQL API'leri güvenlik nedenlerinden dolayı buna izin vermez. Bu durum saldırganların farklı sorgular açmalarını engeller, ancak sorguları değiştirmelerine engel değildir.
Yanlış tip işleme (Incorrect type handling)
[değiştir | kaynağı değiştir]SQLi'ın bu türü, kullanıcı tarafından girilen alanın tür kontrolü düzgün yapılmadığında oluşur. Bir SQL ifadesinde sayısal değer kullanıldığında, kullanıcının girdisinin de sayısal değer olması gereklidir. Bu kontrol yapılmadığı zaman bir güvenlik açığı oluşur. Örneğin:
sorgu = "SELECT * FROM kullaniciBilgileri WHERE id =" + deger + "; "
|
Bu ifadede "id" alanına bir sayının gelmesi amaçlandığı açıktır. Ancak bir string gelmesi bekleniyorsa, son kullanıcı SQL ifadesini istediği şekilde değiştirebilir. Örneğin değer yerine aşağıdaki ifade yazılırsa:
| 1;DROP TABLE kullanicilar |
SQL ifadesi aşağıdaki şekilde olacak ve bu ifade sonucunda kullanicilar tablosu veritabanından silinecektir.
SELECT * FROM kullaniciBilgileri WHERE id=1; DROP TABLE kullanicilar;
|
Körleme SQL enjeksiyonu
[değiştir | kaynağı değiştir]Körleme SQL enjeksiyonu, bir web uygulaması SQLi'na karşı açık olduğunda kullanılır ancak sonuçları saldırgan tarafından doğrudan görülemez. Güvenlik açığı bulunan sayfada veriler ifşa edilemez ama SQL ifadesinin içine gömülmüş olan mantıksal ifade nedeniyle değiştirilmiş veriler görüntülenebilir.
Koşullu yanıtlar (Conditional Responses)
[değiştir | kaynağı değiştir]Veritabanını, sıradan bir uygulamada, mantıksal bir ifadeyi değerlendirmeye zorlar. Örneğin bir kitap inceleme sitesinde, hangi kitabın görüntüleneceğini belirlemek için yandaki sorgu kullanılır. http://kitaplar.ornek.com/incelemeyiGoster.php?ID=5 URL'si sunucunun sorguyu çalıştırmasına neden olur.
SELECT * FROM kitapIncelemeleri WHERE id=Deger(ID);
|
Sorgu sunucuda tamamlanır. Kullanıcı veritabanının, tablonun veya alanların adlarını ve sorgu ifadesini bilmediği için bu kısımlara müdahale edemez. Sadece yukarıdaki URL'nin bir kitap incelemesi getirdiğini görür. Saldırgan, http://kitaplar.ornek.com/incelemeyiGoster.php?ID=5 OR 1 = 1 ve http://kitaplar.ornek.com/incelemeyiGoster.php?ID=5 AND 1 = 2 URL'lerini yüklediği zaman aşağıdaki sorgulara neden olabilir:
SELECT * FROM kitapIncelemeleri WHERE id='5' OR '1'='1';
|
SELECT * FROM kitapIncelemeleri WHERE id='5' AND '1'='2';
|
Bu sorgular sonucunda "1 = 1" URL'si ile orijinal inceleme sayfası geliyorsa veya "1 = 2" URL'si boş sayfa ya da hata sayfası döndürüyorsa, sorgu büyük olasılıkla her iki durumda başarıyla geçmiştir ve site SQL enjeksiyonu saldırılarına açıktır. Hacker, sunucuda çalışan MySQL sürüm numarasını ortaya çıkarmak için tasarlanmış bu sorgu dizesiyle devam edebilir: http://kitaplar.ornek.com/incelemeyiGoster.php?ID=5AND substring(@@version, 1, INSTR(@@version, '.') - 1)=4. Bu sorgu sonrasında MySQL 4 çalıştıran bir sunucuda kitap incelemesi gösterilecek, diğer durumlarda boş sayfa veya hata sayfası gelecektir. Hacker, başka bir saldırı yolu bulana kadar veya hedeflerine ulaşılıncaya kadar sunucudan daha fazla bilgi toplamak için sorgu dizeleri içinde kod kullanmaya devam edebilir.[15][16]
İkincil SQL enjeksiyonu (Second order SQL injection)
[değiştir | kaynağı değiştir]İkincil SQL enjeksiyonu, kötü amaçlı kodlar içeren değerlerin gönderilir gönderilmez yürütülmeyip, bir süre tutulduğu zaman oluşur. Uygulama SQL ifadesini doğru şekilde şifreleyip (encode), geçerli SQL ifadesi olarak depo edebilir. Sonrasında SQL enjeksiyonuna karşı denetimsiz olan uygulamanın başka bir kısmında, depolanan SQL ifadesi çalıştırılır. Bu saldırıyı gerçekleştirmek için saldırganın, gönderilen değerlerin daha sonra nasıl kullanıldığına dair daha fazla bilgiye sahip olması gerekir. Otomatik web uygulaması güvenlik tarayıcıları, bu tür bir SQL enjeksiyonunu kolaylıkla algılayamaz. Dolayısıyla kötü niyetli yazılımların kodun hangi kısmında olduğu manuel olarak kontrol edilmelidir.
Saldırılara karşı önlemler
[değiştir | kaynağı değiştir]SQL enjeksiyonu, iyi bilinen bir saldırıdır ve basit önlemlerle kolayca önlenebilir. 2015'te Talktalk'daki bariz bir SQL enjeksiyon saldırısı sonrasında BBC, böyle büyük bir şirketin SQL enjeksiyonu açıklarının bulunmasının güvenlik uzmanlarını şaşırttığını belirtmişti.[17]
PHP dilinde ortaya çıkması
[değiştir | kaynağı değiştir]SQL alt dilinin dahil olduğu PHP sistemlerde aşağıdaki örnekte gösterildiği gibi ortaya çıkabilir:
<?php
include("digerkodlar.php");
$veri = $_POST['veri'];
# burada veritabanına kaydedilecek olan veri filtreleme yapılmadan POST olarak alınıyor
?>
Güvenlik açığını kapatmak için:
<?php
include("digerkodlar.php");
$veri = htmlspecialchars(addslashes(strip_tags($_POST['veri'])));
# htmlspecialchars gibi bazı filtreleme komutlarıyla güvenlik açığı kapatılır.
?>
Parametreleştirilmiş ifadeler
[değiştir | kaynağı değiştir]Çoğu uygulama geliştirme platformunda, kullanıcıdan gelen veri yerine parametrik ifadeler kullanılır (placeholder veya bind variable olarak da isimlendirilirler). Bir yer tutucu (placeholder) sadece verilen tipte veri saklar. Dolayısıyla SQL enjeksiyonu yalnızca ilginç (ve muhtemelen geçersiz) bir parametre değeri olarak ele alınır.
Çoğu durumda, SQL ifadesi belirlidir ve her parametre tablo olarak değil, skaler olarak saklanır. Kullanıcıdan gelen veri bu parametreye atanır.[18]
Kod seviyesinde zorlamak (Enforcement at the coding level)
[değiştir | kaynağı değiştir]Object-relational mapping (ORM) kütüphanelerini kullanmak, SQL kod yazma gereksinimini büyük ölçüde ortadan kaldırır. Etkin olan ORM kitaplığı, nesne yönelimli (object-oriented) koddan parametrik SQL ifadeleri üretir.
Kaçış (Escaping)
[değiştir | kaynağı değiştir]SQL'de özel anlamları olan karakterlerden kaçınmak gereklidir. SQL DBMS, hangi karakterlerin özel bir anlam taşıdığını açıklar ve kapsamlı bir kara liste (blacklist) sunar. Örneğin her parametre içindeki tek tırnak işareti ('), geçerli bir SQL string oluşturmak için iki tek tırnak ile değiştirilir (''). mysqli_real_escape_string(); fonksiyonunu kullanarak parametrelerden kaçınmak yaygın bir yöntemdir:
$mysqli = new mysqli('hostname', 'db_username', 'db_password', 'db_name');
$query = sprintf("SELECT * FROM `Users` WHERE UserName='%s' AND Password='%s'",
$mysqli->real_escape_string($username),
$mysqli->real_escape_string($password));
$mysqli->query($query);
Bu fonksiyon şu karakterlerin başına ters eğik çizgi (\) ekler: \x00, \n, \r, \, ', " ve \x1a. MySQL'e bir sorgu göndermeden önce veri güvenliğini sağlamak için kullanılır.[19]
PHP'de farklı veritabanı türleri için çeşitli fonksiyonlar bulunur; örneğin PostgreSQL için pg_escape_string() fonksiyonu kullanılır. Ters eğik çizgi eklemek için addslashes(string $str) fonksiyonu kullanılır. Veritabanında sorgulanacak karakterlerin başına ters eğik çizgi (\) eklenmiş bir string döndürür. Bu karakterler tek tırnak işareti ('), çift tırnak işareti ("), ters eğik çizgi (\) ve NUL (NULL bayt) şeklindedir.[20]
Girdi (input) güvenliğini sağlamak için şeffaf bir katman oluşturmak hata eğilimini azaltabilir, ancak tamamen ortadan kaldırmaz.[21]
Örüntü (Pattern) kontrolü
[değiştir | kaynağı değiştir]Integer, float, boolean, string parametreleri, değerlerinin belirtilen tür için geçerli olup olmadığı yönünde kontrol edilebilir. Stringlerin başka örüntülere (pattern) göre de kontrol edilmesi gerekebilir (tarih, UUID, sadece alfanumerik, vb.).
Veritabanı izinleri
[değiştir | kaynağı değiştir]Web uygulamaları tarafından verilen veritabanında oturum açma izinlerini kısıtlamak, web uygulamalarındaki açıkları kullanan SQL enjeksiyon saldırılarının etkinliğini azaltmaya yardımcı olabilir.
Örneğin, Microsoft SQL Server'da bir veritabanı oturum açma işleminde bazı sistem tablolarına erişim kısıtlanabilir. Bu sayede veritabanındaki tüm metin sütunlarına JavaScript eklemeyi deneyen kötü niyetli yazılımlar sınırlandırılmış olur:
deny select on sys.sysobjects to webdatabaselogon;
deny select on sys.objects to webdatabaselogon;
deny select on sys.tables to webdatabaselogon;
deny select on sys.views to webdatabaselogon;
deny select on sys.packages to webdatabaselogon;
Dış bağlantılar
[değiştir | kaynağı değiştir]Kaynakça
[değiştir | kaynağı değiştir]- ^ "SQL Injection". Microsoft. 2 Ağustos 2013 tarihinde kaynağından arşivlendi. Erişim tarihi: 4 Ağustos 2013.
SQL injection is an attack in which malicious code is inserted into strings that are later passed to an instance of SQL Server for parsing and execution. Any procedure that constructs SQL statements should be reviewed for injection vulnerabilities because SQLi Server will execute all syntactically valid queries that it receives. Even parameterized data can be manipulated by a skilled and determined attacker.
- ^ "Imperva Web Application Attack Report" (PDF). 17 Nisan 2016 tarihinde kaynağından (PDF) arşivlendi..
- ^ Sean Michael Kerner (25 Kasım 2013). "How Was SQL Injection Discovered? The researcher once known as Rain Forrest Puppy explains how he discovered the first SQL injection more than 15 years ago". 18 Mart 2014 tarihinde kaynağından arşivlendi..
- ^ Jeff Forristal (25 Aralık 1998). "NT Web Technology Vulnerabilities". Phrack Magazine. 22 Nisan 2017 tarihinde kaynağından arşivlendi.
(8. makale)
- ^ "The Open Web Application Security Project". 23 Nisan 2020 tarihinde kaynağından arşivlendi. Erişim tarihi: 23 Nisan 2020.
- ^ "OWASP Top 10 - 2010: The Ten Most Critical Web Application Security Risks" (PDF) (İngilizce). OWASP Foundation. Erişim tarihi: 12 Nisan 2026.
- ^ "OWASP Top 10 - 2013: The Ten Most Critical Web Application Security Risks" (PDF) (İngilizce). OWASP Foundation. Erişim tarihi: 12 Nisan 2026.
- ^ "WHID 2007-60: The blog of a Cambridge University security team hacked" 18 Nisan 2016 tarihinde Wayback Machine sitesinde arşivlendi.. Xiom. 03-06-2011 tarihinde arşivlendi.
- ^ "WHID 2009-1: Gaza conflict cyber war" 19 Nisan 2016 tarihinde Wayback Machine sitesinde arşivlendi.. Xiom.03-06-2011 tarihinde arşivlendi.
- ^ 18 Haziran 2009 tarihinde Arşivlendi,( Wayback Machine)
- ^ "Third Wave of Web Attacks Not the Last". 22 Nisan 2017 tarihinde Wayback Machine sitesinde arşivlendi. Dark Reading. 29-07-2017 tarihinde arşivlendi.
- ^ Danchev, Dancho (23-01-2007. "Mind Streams of Information Security Knowledge: Social Engineering and Malware"[ölü/kırık bağlantı]. Ddanchev.blogspot.com. 03-06-2011 tarihinde alıntılandı.
- ^ Deltchev, Krassen. "New Web 2.0 Attacks" 16 Ağustos 2017 tarihinde Wayback Machine sitesinde arşivlendi.. B.Sc. Thesis. Ruhr-University Bochum. 18-02-2010 tarihinde arşivlendi.
- ^ IBM Informix Guide to SQL: Syntax. Overview of SQL Syntax > How to Enter SQL Comments, IBM
- ^ macd3v. "Blind SQL Injection tutorial" 14 Aralık 2012 tarihinde Wayback Machine sitesinde arşivlendi.. 6 Aralık 2012 tarihinde arşivlendi.
- ^ Andrey Rassokhin; Dmitry Oleksyuk. "TDSS botnet: full disclosure" 9 Aralık 2012 tarihinde Wayback Machine sitesinde arşivlendi.. 6 Aralık 2012 tarihinde arşivlendi
- ^ "Questions for TalkTalk - BBC News" 26 Ekim 2015 tarihinde Wayback Machine sitesinde arşivlendi.. BBC News. 25-10-2015 tarihinde arşivlendi.
- ^ "SQL Injection Prevention Cheat Sheet". Open Web Application Security Project. 3 Mart 2012 tarihinde arşivlendi.
- ^ "mysqli->real_escape_string - PHP Manual 17 Nisan 2016 tarihinde Wayback Machine sitesinde arşivlendi.". PHP.net.
- ^ "Addslashes - PHP Manual 5 Eylül 2011 tarihinde Wayback Machine sitesinde arşivlendi.". PHP.net.
- ^ "Transparent query layer for MySQL 11 Kasım 2010 tarihinde Wayback Machine sitesinde arşivlendi.". Robert Eisele. 8 Kasım 2010