SQL Injection:Veritabanı Injection Örnek Sorgular

Merhaba arkadaşlar,

Bu makalemizde SQL Injection ile alakalı ufak uygulamalar yapacağız.

Günümüzde İnternetin keşfiyle birlikte müthiş bir bilgi patlaması yaşandı. İnsanlar ellerinde olan bilgileri internet aracılığıyla paylaşmaya ve başkaları tarafından paylaşılmış olan bilgilere ulaşıp yararlanma imkanınına kavuştular.Bilgiler önce salt HTML kodlarında saklanırken bunun verimli olmadığı anlaşıldı ve dinamik bir dil (Perl, PHP, ASP, ASP.NET , CGI, CFM, JSP vs.) ve veritabanı sistemleri (MySQL, SQL Server, ORACLE, DB2, Access vs.) i web uygulamalardaki yerlerini almaya başladılar. Veritabanı sistemleri sayesinde daha çok veri saklandı, verilere daha hızlı erişildi ve hemen hemen neredeyse veritabanı kullanmayan web uygulamaları kalmadı. Geliştirilen SQL veri sorgulama dili sayesinde veriler veritabanından etkili bir şekilde çekildi ve kullanıma sunuldu. Fakat internetin getirmiş olduğu bir zaaf vardı: Güvenlik Eksikliği. Bilgiler, internette güvenli bir şekilde paylaşılmalıydı ve herkesin kendi yetkisi dahilinde bilgi ve belgeye

ulaşabilmesi sağlanmalıydı. Bunun için web sunucularda güvenliğe önem verildi. Güvenlik kontrolleri arttırıldı ve daha güvenli bilgi paylaşımıimkanı sunuldu. Bu sırada gözden kaçan bir nokta vardı: Uygulama Güvenliği. Acaba yazılan uygulamalar yeterince güvenli miydi? Bu gözden kaçan nokta aslında büyük bir güvenlik açığı oluşturdu: SQL Injection.

SQL Injection kelime manasıyla da anlaşılabileceği gibi SQL sorgularının arasına dışarıdan zararlı veri ekleme işlemine verilen isimdir. Dinamik web uygulamalarında bir veritabanı ve o veritabanı üzerinde çalışan SQL sorguları vardır. Bu sorgular masum amaçlı bir veya birden fazla tablodan veriler çekerek etkileşimi sağlamayı amaçlamaktadır. Ama dışarıdaki

kullanıcının uygulamaya gelen girdilere zararlı veri karıştırması sonucu masum sorgularımız korkunç bir faciaya sebep olurlar.Web uygulamaları genelde kullanıcıyla etkileşime geçerek dinamik bir arayüz sunarlar. Bu sırada kullanıcıdan bir takım girdiler(Formdan, URL Sorgularından, çerezlerden vs.) alırlar ve bunu uygulama içinde işleme sokarlar ve belli bir çıktı verirler. Bu sırada uygulamamızda bir takım veritabanına erişecek kodlar, veritabanı üzerinde bir takım sorgular çalışırlar ve belli bir veri elde ederler. Sonra da bu veriyi düzenleyip kullanıcıya gönderirler. İşte SQL Injection bu işlemler sırasında devreye girer. çünkü veritabanı üzerinde bir takım sorgular çalıştırılmak istenmiştir. Böylece zararlı sorgularımız veritabanı üzerinde çalıştırılmış olur.Neticede SQL Injection bir veritabanına SQL üzerinden sızma! Olarak özetlenebilir.Yazılan basit, masum SQL ler hiç farkında olunmadan yapması gereken işlemler dışında programcının istemeyeceği sonuçlara yol açabilir.Bu durum ,verileri dış dünyaya verme ya da veritabanında bir paket cağırma vs. şeklinde olabilir.SQL Injection olması için veritabanında yazılan kodun “dynamic sql(dynamic sql)” olması gerekir.Yani SQL , gelecek parametrelere göre runtime esnasında oluşturulmalıdır.(“bind variable”) kullanmanın tek avantajının performanslı kodlar yazmak olmadığı, veritabanı güvenliği (database security) içinde önemli olduğu buradan anlaşılmaktadır).SQL Injection’ın uygulamamıza verebileceği zarar sadece sorgu çalıştırmaktan ibaret değildir. Sistem, veritabanı ve uygulama yetkilerine göre sistemi tamamen devre dışı bırakabileceği gibi aynı ağdaki internete açık olmayan kurumsal makinelerdeki bilgileri erişimden, o ağ kaynaklarını kullanarak başka yerlere saldırı yapmaya kadar uzanabilen bir yolu açmış demektir.

Peki bu nasıl oluyor? Böyle bir ortamı sağlamak için basit bir yapı oluşturalım.Elimizde müşterinin ad soyad telefon fax ve tip bilgilerinin tutulduğu bir “customer” tablomuz olsun :

Oluşturduğumuz tabloya bir kaç veri giriyoruz.

Müşterinin soyadını verince telefon numarasını veren bir fonksiyonun aşağıdaki gibi yazıldığını varsayalım:

Ortamımızı hazırladık.Şimdi de mesela soyadı “Yilmaz” olan müşterinin telefon numarası alalım;

Buraya kadar her şey yolunda, soyadını verdiğiniz müşterinin telefon numarasını alabiliyorsunuz.

Diyelim ki bana tüm müşterilerin telefon numarası lazım Bunu elimizdeki bu fonksiyonla getirebilir miyiz sizce ? Gönderilen parametreyi biraz düzenleyip!!! deneyelim :

Evet, başardık  Elimizde sisteme kayıtlı tüm telefon numaraları var artık.Peki bunu nasıl basardık? “getCustPhone” fonksiyonuna bir göz atalım.Dinamik SQL şu şekilde tasarlanmış ;

Son örneğimizde gönderdiğimiz gibi “’Yilmaz”’ || ‘ or exists (select 1 from sys.dual) and ‘’x’’ = ‘’x’;” gönderirsek oluşan SQL stringi ise :

şeklinde!!!”customer_name = ” eşitliğini sağ tarafına SQL in seyrini değiştirecek fazladan SQL ler yazabildik! (Ekstra yazdıgımız ‘x’ = ‘x’ sadece açık kalacak bir tırnağı kapamak için kullanılıyor)

Şimdi bu örnekleri arttıralım :Kurduğumuz “connection”’ın hangi “user” üzerinden yapıldıgını bulalım :

Bu örnekleri arttırmak mümkün.Hatta diğer bir veritabanına giden bir linki biliyorsak yukarıdakilere benzer örneklerle oradaki bilgilere ulaşmak bile!Sonuç olarak SQL Injection durumları karşılaşılmayacak seyler değil ama korunulmasıda gayet basit.”Bind Variable” kullanın!

Bir SQL Injection kullanan saldırının anatomisi

Ne kadar sıklıkta gözükür?

* Dinamik websiteleri için en sık gözüken güvenlik açığıdır!

*Uygulama içerisinde yer alan bir çatlaktır. VT veya web sunucu problemi değildir.

* Bir çok programcı bu açıktan habersizdir.

* Webde yer alan birçok uygulama hala SQL Injection barındırmaktadır.

* İnternette yer alan çözümler çok da yeterli değildir.

Hedef Sistemler

* Hemen hemen tüm SQL veritabanı yönetim sistemleri ve programlama dilleri tehdit altındadır:

*MS SQL Server, Oracle, MySQL, Postgres, DB2, MS Access, Sybase, Informix vs.

*Genelde bu dillerde geliştirilmiş uygulamalarda yer almaktadır:

*Veritabanına erişen Perl ve CGI scriptleri • ASP, JSP, PHP , ASP.NET, CFM…

*XML, XSL ve XSQL

*Javascript

*VB, MFC, ve diğer ODBC tabanlı araçlar ve API ’ler

*Raporlamalar ve VT Uygulamaları ve bir çok dil…

SQL Injection Nasıl çalışır?

En çok rastlanan login sorgusu:

PHP- Kodu:SELECT * FROM users WHERE login = ‘ musa ’ AND password = ‘ 123 ’

ASP içerisinde, kullanıcıdan gelen verileri MS SQL Server’da denetlemek üzere şu şekilde bir SQL ifadesi oluşturulur.

PHP- Kodu:sql = ” SELECT * FROM users WHERE login = ’ ” + formusr + ” ’ AND password = ’ ” + formpwd + ” ’ “;

SQL Injection için formusr değişkenine şu şekilde bir ifade geldiğini düşünelim

PHP- Kodu: formusr = ’ or 1=1 – –formpwd = herhangi bir string

Sorgumuzun son hali aşağıdaki gibi olacaktır:

PHP- Kodu: SELECT * FROM users WHERE login = ’ ’ or 1=1 — AND password = ‘ herhangi… ’

Bildiğiniz gibi – MS SQL Server ve MS Access için SQL sorgularında özel bir anlam taşımaktadır. – karakterlerinden sonraki gelen herşey yorum(comment) olarak kabul edilir ve veritabanı motoru tarafından işlenmez.

Veritabanımızı oluşturacak SQL sorguları:

PHP- Kodu:create table users( id int, username varchar(255), password varchar(255), privs int)insert into users values( 0, ’admin’, ’admin’, 100 )insert into users values( 0, ’guest’, ’guest’, 1 ) Login Sayfamız: login.aspx

PHP- Kodu:

<HTML><HEAD><TITLE>Login Page</TITLE></HEAD><BODY bgcolor=’ 000000’ text=’cccccc’><FONT Face=’tahoma’ color=’cccccc’><CENTER><H1>Login</H1><FORM action=’process_login.asp’ method=post><TABLE><TR><TD>Username:</TD><TD><INPUT type=text name=username size=100% width=100></INPUT></TD></TR><TR><TD>Password:</TD><TD><INPUT type=password name=password size=100% width=100></INPUT></TD></TR></TABLE><INPUT type=submit value=’Submit’><INPUT type=reset value=’Reset’></FORM></FONT></BODY></HTML>

Login işlemini kontrol eden asp scriptimiz:

PHP- Kodu:

<HTML><BODY bgcolor=’ 000000’ text=’ffffff’><FONT Face=’tahoma’ color=’ffffff’><STYLE>p { font-size=20pt ! important}font { font-size=20pt ! important}h1 { font-size=64pt ! important}</STYLE><%@LANGUAGE = JScript %><%function trace( str ) { if( Request.form(“debug”) == “true” ) Response.write( str );} <HTML><BODY bgcolor=’ 000000’ text=’ffffff’><FONT Face=’tahoma’ color=’ffffff’><STYLE>p { font-size=20pt ! important}font { font-size=20pt ! important}h1 { font-size=64pt ! important}</STYLE><%@LANGUAGE = JScript %><%function trace( str ) { if( Request.form(“debug”) == “true” ) Response.write( str );} //Bağlantıyı Oluşturalım var username; var cn = Server.createobject( “ADODB.Connection” ); cn.open( “Driver={SQL Server};server=localhost;uid=sa;pwd=sa;database=No rthwind” ); username = new String( Request.form(“username”) ); if( username.length > 0) { Login( cn ); } cn.close();}Main();%>

Şimdi gelin Tek tırnağın(’) Gücünü hep birlikte adım adım analiz edelim.

*Önce string parametreyi kapattı.

*Ardından gelen bütün ifadeler SQL sorgusu olarak işlendi.

*Ve böylece sisteme yetkisiz erişim hakkı sağlandı.

çözüm nedir?

İnternette yer alan genel çözüm (‘) tek tırnağı 2 tane tek tırnakla (‘’) değiştirmeniz böylece açılan bir yolu kapatmanız yönünde. Ama aslında bu çok da yeterli değil. Nedenine değinmeden önce database string fieldları dışında başka ne gibi fieldlarda sql injection uygulanabilir, ona bakalım.

Nümerik Alanlar:Eğer nümerik bir alan varsa veritabanında? Evet, onlar da sql injection uygulanabiliyor.

  • PHP- Kodu:
  • SELECT * FROM clients WHERE account = 12345678 AND pin = 1111
  • PHP/MySQL login yapısı:
  • PHP- Kodu:
  • $sql=”SELECT * FROM clients WHERE “. “account = $formacct AND ” . “pin = $formpin”;
  • Nümerik Alana Injection
  • PHP- Kodu:
  • $formacct = 1 or 1=1 # $formpin = 1111
  • Sorgumuzun son hali:
  • PHP- Kodu:
  • SELECT * FROM clients WHERE account = 1 or 1=1 # AND pin = 1111

MySQL için SQL cümleciklerindeki # (diyez) karakteri yorumlardan önce gelmektedir. Böylece sorgumuzun geri kalan kısmı işleme alınmayacaktır.

Veritabanında tablomuzu oluşturacak SQL sorguları:

PHP- Kodu:

DROP TABLE IF EXISTS `accounts`;CREATE TABLE IF NOT EXISTS `accounts` (`id` bigint(20) unsigned NOT NULL auto_increment,`account` bigint(20) NOT NULL default ’ 0’ ,`pin` bigint(20) NOT NULL default ’ 0’ ,`user_name` varchar(128) NOT NULL default ’’,PRIMARY KEY (`id`)) TYPE=MyISAM AUTO_INCREMENT=3 ;—- Tablo döküm verisi `accounts`–INSERT INTO `accounts` VALUES (1, 123, 123, ’ULKER’);INSERT INTO `accounts` VALUES (2, 456, 456, ’MUSA’);

SQL Injection Karakterleri

PHP- Kodu:’ veya ” string karakter ayracı — veya # tek satır yorum /*…*/ çok satır yorum + toplama, concatenate işlemi (veya URL’de space) || (çift pipe) concatenate (Oracle ve PostgreSQL’de) % wildcard-ayraç ?Param1= xyz &Param2= klm URL parametreleri PRINT non-transactional komut olarak @variable local değişken @@variable global değişken waitfor delay ’0:0:10‘ süre gecikmesi # Access’de tarih ayıracı – çıkarma – Check Constraint Range

*SQL Injection Bulunabilecek Yerler

*Formlardaki alanlar

*URL sorgu stringlerindeki parametreler

*Cookieler

Bu alanların iyi kontrol edilmesi gerekir!

*Tek tırnaktan( ’ ) Korunmak: Bir fonksiyon yardımıyla ( ’ ) karakterini ( ’ ’ ) ile değiştirebiliriz.PHP- Kodu:SELECT CHAR(49) + CHAR(39) + CHAR(32) + CHAR(79) + CHAR(82) + CHAR(32) + CHAR(49) + CHAR(61) + CHAR(49) + CHAR(45) + CHAR(45)

Sonuçta, Tek tırnak ( ’ ) karakterini temizlesek bile CHAR ve Concat Operatörünü(+) de gelen inputtan arındırmamız gerekiyor.

Sql Enjeksiyonundan Korunma Yaklaşımları:

Genel olarak 3 temel yaklaşım var:

1. Sadece İyileri Kabul Etmek

2. Kötüleri Reddetmek

3. Kötüleri Filtreleyerek Kabul Etmek

*Sadece İyileri Kabul Etmek:Kullanıcının sadece belli karakterleri kullanmasına izin vermek. (abcd……..yz012….89 gibi) Bazı bankalarda bu yöntem kullanıyor. Gelen inputu karakter karakter kontrol edilmesi gerekiyor.

*Kötüleri Reddetmek:Güvenli sayılabilir. Ama bazen kullanıcı nerede hata yaptığını anlamaz.

“SELECT”, “ INSERT”, “ UPDATE”, “ DELETE”, “DROP”, “OR”, “,”, “+”

vb. gibi kelimeler barındırıyorsa devam etmeden direk reddedilir.

*Kötüleri Filtreleyerek Kabul Etmek:En basit korunma yöntemidir. Kötüleri reddetme yönteminde olduğu gibi INSERT + vs özel karakterleri, SQL spesifik kelimeleri arındırarak kabul etmek.Temel bir koruma sağlar, ama yeterli değildir.

Önemli:Korunmak için genel kontrol listesinin oluşturulması.

1. Bütün girdileri kontrol edin!

2. Tüm gelen inputları aksini ispatlayana kadar zararlı olduğunu düşünün.

3. Sisteminize uygun veriye alın ve gerisini reddedin

4. Regular Expressions kullanarak zararlı karakterlerden verinizi temizleyin.

5. Numeric alanları IsNumeric tarzı kontrollerden geçirin.

6. Kodlarınızı en düşük yetkiyle çalıştırın

1. MS SQL için ASLA “sa” yı kullanmayın!

2. MySQL için ASLA “root” kullanmayın!

3. MSSQL için system stored procedürlerinin çalıştırılmasına izin vermeyin

7. Stored Procedure veya parametrize edilmiş SQL cümlecikleri kullanın

8. Database hatalarını kullanıcıya göstermeyin.

Sonuç:

*SQL Injection küçümsenmemesi gereken büyük bir güvenlik açığıdır.

* Yeni yazılımlar çok dikkatli kodlanmalı, eskiler çok dikkatlice gözden geçirilmelidir.

* Burada gösterilmeyen birçok ileri SQL Injection yöntemleri vardır.

Bir cevap yazın

E-posta hesabınız yayımlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir

error: Content is protected !!