Başlangıç Seviye SQL Injection Atak Türevleri
Öncelikle SQL Injection zafiyetinin ne olduğunu anlamamız gerekiyor çünkü otomatik araçlar bizim sadece verdiğimiz komutlar üzerinden işlemler gerçekleştirirler. Bu araçları kullanım amacımız ise bilgileri ele geçirmek yahut manipüle etmek içindir. SQL türevi açıkları manipüle etmek için türlü çeşit yollar vardır bunların ana metodları olduğu gibi yan metotları da mevcuttur. Öncelikle küçük bir sql sorgusuna tanık olalım ve onun içinde geçen SQL açığını tanıyalım;<?php
$id = $_POST["newsid"];
$q = "select * from haber where id='$id' LIMIT 0,1";
$ret = mysql_query($q);
$row = mysql_fetch_array($ret);
if($row)
{
echo '<font color= "#0000ff">';
echo 'Başlık:'. $row['title'];
echo "<br>";
echo 'Okuma Sayısı:' .$row['hit'];
echo "</font>";
}
else
{
echo '<font color= "#900">';
print_r(mysql_error());
echo "</font>";
}
}
else { echo "hata, düzenli bir data çağırınız ";}
?>
Yukarıdaki kod bloğunda görüldüğü üzere bir form üzerinden gönderilecek bilginin simülasyonu oluşturulmuş ve PHP kod bloğuyla bu bilginin çağırılması istenmiştir. Bilgiyi bir kutucuk üstünden çağırdığımızda ekrana direkt olarak çıktısını verecektir. Burada ana problem
$id değişkenidir, bu değişken hiçbir önlem alınmaksızın direkt olarak tanımlanmış ve kutucuk üstünden mysql tabanına keyfi olarak data işlemektedir. Kod bloğunu ben bir varsayım olarak ekledik POST değil de GET datası olarakta gönderebilirdik, örneğini vereceğimiz birkaç hazır script var orada zaten GET olarak ele alacaktır sadece injekt oldukları alanlar farklı; birisi form üstünden data gönderiyor, birisi direkt parametre üstünden data gönderiyor buna fazla takılmamak lazım zaten kodu farazi olarak ekledim. Istersen bir küçük kod blogu bakalım bu alanda daha iyi pekişeceğine inanıyorum;
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "
http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="
http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Less-1 **Error Based- String**</title>
<link rel="stylesheet" href="../index.html_files/freemind2html.css" type="text/css"/>
</head>
<body>
<div style=" margin-top:70px;color:#FFF; font-size:23px; text-align:center">
<h1><span class="style1">Welcome </span><font color="#FF0000">to SQL injection Master Course </font></h1>
<h1><span class="style2">Lesson-1</span></h1>
<h1><span class="style4">Hint : Error based string</span> <br>
<font size="3" color="#666666">
<?php
//including the Mysql connect parameters.
include("../sql-connections/sql-connect.php");
// take the variables
if(isset($_GET['id']))
{
$id=$_GET['id'];
//logging the connection parameters to a file for analysis.
$fp=fopen('result.txt','a');
fwrite($fp,'ID:'.$id."\n");
fclose($fp);
// connectivity
$sql="SELECT * FROM users WHERE id='$id' LIMIT 0,1";
$result=mysql_query($sql);
$row = mysql_fetch_array($result);
if($row)
{
echo '<font color= "#0000ff">';
echo 'Your Login name:'. $row['username'];
echo "<br>";
echo 'Your Password:' .$row['password'];
echo "</font>";
}
else
{
echo '<font color= "#900">';
print_r(mysql_error());
echo "</font>";
}
}
else { echo "Please input the ID as parameter with numeric value";}
?>
</font> </h1>
</div>
<div class="botton_fix">For more please visit : <a href="
http://www.hiteshchoudhary.com" target="_blank">
www.hiteshchoudhary.com</a></div>
</br></br></br><center>
</center>
</body>
</html>
Yukarıdaki kod bloğunun sayfaya dökülmüş hali üstüne bir örnekleme yapalım;
$_GET['id']
Şöyle bir kod blogu var bu parametre üstünden bir datanın SQL kaynağına data göndereceğini açıklıyor.
gördüğün gibi parametremiz ?id=1 oldu, 1 sayısını ben çağırıyorum burada “?” işareti ise parametreler arası geçişi açıklıyor.
İmajda da göreceğin üzere bir adet " ’ "(tırnak) ile hata almaya çalışıyoruz(her zaman ekrana hata çıktısı vermez) bize geri döndürdüğü hata ise MYSQL’in tanımadığı bir datayı çağırdığı ve bu yüzden hata verdiğidir. İstediğimiz gibi hatayı aldık şimdi bu hatayı anlayalım tekrardan;
$sql="SELECT * FROM users WHERE id='$id' LIMIT 0,1";
görüldüğü üzere id= bölümüne gelmesi gerek id yerinde artık bizim “tırnak” dediğimiz karakterimiz var bu aslında bir nevi fuzzing yöntemidir, şöyle ki; parametreyi gönder ve hata varsa orayı sömür biz de tam olarak bu işi yaptık ve gerekli hatayı aldık, burada korumasız bir şekilde bir değişkenin($id) sorgu içine tanımlanmasının ne derece büyük zararlar getireceğini göreceğiz;
yukarıda ki imajda da görüldüğü gibi artık kolon arama işlemlerine geçiyoruz ve hata verene kadar order by 1, order by 2 vs. gibi aramalara devam ediyor istenilen kolon sayısına ulaştıktan sonra karşımıza bu şekilde bir hata mesajı gelecek yani bizim kaçtane kolonumuz var ve biz bu kolonların üstünden nasıl data çağırırız bize bunu anlatıyor. burada sayımız ‘4’ gösteriyor yani 4. sayıya geldiğimizde hata verdi o yüzden 3 tane kolon olduğunu anlıyoruz çünkü 4. sayıya gelene dek ses çıkarmadı 4. sayıda ise hata verdi işlem bu kadar basit.
Evet artık union(sorguları birleştirmeye yarar) sorgusuyla atağımızı başarılı bir şekilde gerçekleştirebiliyoruz ve version almayı başardık bile ama bir sonraki adımımız yazılım üzerinde bulunan kullanıcı adı, şifre ve maillerin çekilmesi oluyor şimdi bu işleme başlayabiliriz;
http://127.0.0.1/egit//Less-1/?id=-1' union all select 1,2,table_name from information_schema.tables where table_schema=database() limit 3,1-- -
yukarıda ki sorgumumuzda da gördüğün üzere artık tablo isimlerini çekmeye başlayabiliriz, unutmadan ben ilk resimde @@version olarak çektirmişim sen uygulayacağın alanda database() olarak çektirmelisin bilgin olsun.
Database girip baktığında(show databases
information_schema göreceksin bu bizim şemamızdır yani bizim tablo ve kolon yapılarımız dahil olmak üzere tüm yapılara şeklini veren yapıdır ondan dolayı;
from information_schema.tables diyoruz. Yani şemanın tablo bölümünü referans göster çünkü ben bu yapıyı kullanacağım ve 1,2,table_name dediğimiz alan ise tablo isimlerinin ekrana çıktısını vermesi için kod enjekte ettiğimiz alandır. Burada table_name yazdığımız yer ise 3. kolon alanıdır bunu zaten alıştırmayla çok çabuk kavrayacağına eminim. Ve artık tabloları limit yahut order by vasıtasıyla çektirebilir dataları ele geçirebiliriz.
http://127.0.0.1/egit//Less-1/?id=-1' union all select 1,2,group_concat(column_name) from information_schema.columns where table_name='users'-- -
Gördüğün üzere istersek limit kullanabiliriz istersek group_concat ile çektirebiliriz önceki örnekde de istersen kullanabilirsin ben bilgin olması amacıyla limit göstermiştim. Artık kolon isimlerini alıyoruz ve bizim işimize yarayacak olanlar ise belli;
Bu kolonlar üstünden işlem yaptığımızda bilgiler elimize temiz bir şekilde geçecek tabii md5, sha vs. gibi datayı koruma yöntemleri yok ise. Dikkat ettiysen burada table_name='users' kullandık yani önceki sorguda elde ettiğimiz tablo ismini küçük bir iç sorguyla ana sorgumuzun içine ekledik, ve group_concat(column_name) çağırdık nereden ? from information_schema.columns şemamızdan, group_concat olmaksızında çağırılabilirdi silerdik o sorguyu sadece column_name kalırdı ve limit ile işlerimizi hallederdik ama böylesi daha basit tabi. Ve geldik en kolay yerine mevzunun resimde gördüğümüz ve yazıda da belirttiğimiz dataları çekelim;
http://127.0.0.1/egit//Less-1/?id=-1’ union all select 1,2,concat(id,0x3a,username,0x3a,password) from users-- -
Artık sorgumuz tamamlandı imajda da görüldüğü üzere kullanıcı adı: some ve şifre:some. Burada 0x3a bir hex karakter yani ‘:’(iki nokta üst üste) ben şahsi olarak dataları ayırmak için kullanıyorduk bu karakteri bilgin olsun dataları aldık peki nerden ? from users yani kullanıcı tablosundan. Artık işlemlerimiz tamam şimdi sana bunu denemen için birkaç yol göstermek gerekecek ama denemeleri yaptığımız scripti kurmanı ve kodları anlamanı istiyorum.
Unutmadan, database son hali;
http://s000.tinyupload.com/index.php?file_id=08741245839258160684 13