Sql injection hakkında herşey

By LovelessGent
Ağu 16th, 2013
0 Comments
1478 Views
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 Attack (sql injection hakkında herşey)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 İnjection

(Onur Serhat Uygur’un yazmış olduğu makale okumanızı tavsiye ederim)   Peki bu nasıl oluyor?Böyle bir ortamı sağlamak için basit bir yapı oluşturalım.Elimizde müşterinin ad soyad tlelefon fax ve tip bilgilerinin tutulduğu bir “customer” tablomuz olsun :

Kod:
create table customers(
CUSTOMER_FORNAME VARCHAR2(30),
CUSTOMER_SURNAME VARCHAR2(30),
CUSTOMER_PHONE VARCHAR2(30),
CUSTOMER_FAX VARCHAR2(30),
CUSTOMER_TYPE NUMBER(10)
);

Şimdi de birkaç veri girelim :

Kod:
declare
begin
insert into customers values(’Ali’,’Yilmaz’,999444888,999444889,3);
insert into customers values(’Ahmet’,’Celik’,999555888,999555889,2);
insert into customers values(’Veli’,’Gocer’,999777888,999777889,1);
commit;
end;

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

Kod:
create or replace procedure getCustPhone(p_surname varchar2)
is
type refCursor ref cursor;
rc refCursor;
thePhone customers.customer_phone%type;
stmt varchar2(32767):=’select customer_phone ‘||
‘from customers ‘||
’where customer_surname=”’||
P_surname||”’’;
begin
dbms_output.put_line(’select str : ‘|| stmt);
open rc for stmt;
loop
fetch rc into thePhone;
exit when cv%notfound;
dbms_output.put_line(’customer phone : ‘||thePhone);
end loop;
close rc;
end getCustPhone;

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

Kod:
declare
cust varchar2(200) := ‘Yilmaz’;
begin
getCustPhone(cust);
dbms_output.put_line(’TEST SONLANDI….’);
end;
CIKTI :
select str : select customer_phone from customers where customer_surname=’Yilmaz’
customer phone : 999444888

TEST SONLANDI…. 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 :

Kod:
declare
cust varchar2(200) := ‘Yilmaz”’ || ‘ or exists (select 1 from sys.dual) and ‘’x’’ = ‘’x’;
begin
getCustPhone(cust);
dbms_output.put_line(’TEST SONLANDI….’);
end;
CIKTI :
select str : select customer_phone from customers where customer_surname=’Yilmaz’ or exists (select 1 from sys.dual) and ‘x’ = ‘x’
customer phone : 999444888
customer phone : 999555888
customer phone : 999777888

TEST SONLANDI…. 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ış :

Kod:
stmt := ’select customer_phone ‘||’from customers ‘||
‘where customer_surname=”’||p_surname||”’’;

Burada “p_surname” değişkenine biz ne yazarsak “stmt” SQL stringi o şekilde oluşacak!!! Zaten SQL Injection durumuna sebeb olan noktada burası.”Yilmaz” gönderdiğimizde olusan SQL string : select customer_phone from customers where customer_surname=’Yilmaz’ 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 :

Kod:
select customer_phone from customers
where customer_surname=’Yilmaz’
or exists (select 1 from sys.dual) and ‘x’ = ‘x’

şeklinde!!!”customer_name = ” eşitliğini sağ tarafına SQL in seyrini değiştirecek fazladan SQL ler yazabildik! (Ektra 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 :

Kod:
declare
cust varchar2(200) := ‘Yilmaz”’ || ‘ union select sys.login_user from sys.dual where ‘’x’’=’’x’;
begin
getCustPhone(cust);
dbms_output.put_line(’TEST SONLANDI….’);
end;
CIKTI :
select str : select customer_phone from customers where customer_surname=’Yilmaz’ union select sys.login_user from sys.dual where ‘x’=’x’
customer phone : 999444888
customer phone : CUSTINFOUSER

TEST SONLANDI….

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!
Şimdi İ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 imkâ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.) ikilisi 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 Nedir?

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. 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. Click this bar to view the full image. Shot at 2007-07-14 Şekil-1: 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.asp PHP- Kodu:
Kod:
<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><[email protected] = 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><[email protected] = 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:

Kod:
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:

Kod:
$formacct = 1 or 1=1 # $formpin = 1111

Sorgumuzun son hali: PHP- Kodu:

Kod:
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:

Kod:
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’);

Login ekranımızın ve kontrollerimizin olduğu php kodları: PHP- Kodu:

Kod:
require(’classes.php’);
session_start();
$db = new db("root","","sql_demo","localhost");
error_reporting(0);
if($_POST[’account’] && $_POST[’pin’]){
if($user=$db->get_row(" SELECT * FROM accounts WHERE account=".$_POST[’account’]." AND pin=".$_POST[’pin’]." LIMIT 1 ")){
echo "Hoş geldiniz $user->user_name ";
}
else
echo "Erişim engellendi !!";
}
else {
?>
<html>
<head>
<title>Güvenli Bir İnternet Sitesi </title>
</head>
<bOdy>
<form id="login" action="<?=$_SERVER[’PHP_SELF’] ?>" method="POST" >
Kullanıcı adı: <input type="text" value="<?=$_POST[’acocount’]?>" size="24" maxlength="20" name="account" /> 
şifre :<input name="pin" type="text" size="24" maxlength="20" value="<?=$_POST[’pin’]?>"/>
<input type="submit" value="Gönder" />
</form>

Örnekler: kullanıcı: 1 or 1=1 # şifre: 1111 </bOdy></html> <?php} ?> 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. • Peki ama ASCII kodu??? ASCII KOD DEĞER 32 Boşluk 39 ’ 45 – 49 1 61 = 79 O 82 R PHP- Kodu:

Kod:
SELECT CHAR(49) + CHAR(39) + CHAR(32) + CHAR(79) + CHAR(82) + CHAR(32) + CHAR(49) + CHAR(61) + CHAR(49) + CHAR(45) + CHAR(45)

Sql injection hakkında herşey

  • Sql injections
  • sql injection nasıl yapılır
  • sql injection kodları
  • sql injection açığı
  • sql injection korunma
  • sql injection nedir
  • sql injection hack
  • sql injection indir
  • php sql injection

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.

Sql injection

Korunmak için genel kontrol listesi

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.

Alıntıdır: Fuub

Bir Cevap Yazın

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

Connect with Facebook