|
.NET ve Uygulama Güvenliği - 1 |
|
Gönderiliyor lütfen bekleyin... |
|
|
.NET Uygulama Güvenliği
Reflexil isimli bir araç tanıtma amaçlı yazdığım blog girdisinden sonra gelen geri dönüşlerden sonra uygulama güvenliği çok merak edilen ve birçok senaryolarda nasıl bir yaklaşımın tam kestirilemediği bir konu olduğunu gördüm.
Bu makalemizde geliştirilen bir dll ya da exenin (bundan sonra assembly olarak
bahsedeceğiz) müşterilere dağıtım aşaması ve sonrasında güvenliği üzerindeki
konuları çeşitli senaryolarla ortaya koyup hangi durumlarda neler
yapabileceğimizi inceleyeceğiz.
Senaryolarımızda basit bir uygulama kullanalım. Uygulamamızı aşağıdaki resimde
de göreceğiniz gibi textbox'a girilen değer 123 ise buton'a tıklandığında o
kişinin hesabından havale yapacak şekilde düşünelim.
Havale işlemini yapacak sınıfımız da başka bir assembly (dll) içerisindedir. Ana
uygulamamız bu dll'i kendisine referans olarak ekleyerek kullanmaktadır. (Bu
örneği bu şekilde tasarlamamızdaki amaç farklı senaryoları canlandırmaktır. Bu
senaryo için tüm yapılanlar havale yapacak kodun ana uygulama içerisinde
olmasını durumunda da geçerlidir.)
Havale işlemimizi yapacak sınıfımızın kodları aşağıdakı gibidir.
public class Havale
{
public bool HavaleYap(int Kimden, int Kime, int Miktar,string sifre)
{
if (!sifre.Equals("123"))
{
return false;
}
int kesilenPara = 0;
if (Onayla(Kimden))
{
kesilenPara = (int)(Miktar * 0.1);
//havale islemleri yapilmistir!
return true;
}
else
{
return false;
}
}
private bool Onayla(int Kimden)
{
//musteri bilgileri kontrol edildi
return true;
}
}
|
Senaryo 1
Uygulamamızı paketledik ya da baska bir dağıtım yöntemi ile müşterimize verdik.
Bu durumda havale yapacak dll tüm müdahalelere açıktır. Meraklı bir programcının
ilk yapacağı işlemlerden birisi Reflector veya sevgili Özcan Değirmencinin geliştirmiş olduğu Fox Decompiler ile havale
yapan kodların bulunduğu assemblyyi açarak kodları incelemek olacaktır.
Kodlar
hakkında genel bir bilgi edindikten sonra ilk yapacağı işlem benzer bir assembly geliştirerek
bizim geliştirdiğimiz assemblyi silip kendisininki ile değiştirmek olacaktır. Bu durumda uygulamamız
herhangir bir hata vermeden çalışmaya devam edecektir.
Çünkü uygulamamız çalışma zamanında clHavale.dll isimli dosyayı yüklemeye çalışacak eğer bulursa yükleyip
içerisindeki kullanılan tipleri(class, struct , enum vs) bulup işlemleri gerçekleştirecektir.Dolayısı ile
uygulamamız dll ile ilgili hiçbir özel bilgiye sahip olmadığından bu dll'in
değişip değişmediği ya da üretici firma tarafında geliştirilen dll olup olmadığı
ile ilgili herhangi bir onay mekanizması devreye giremeyecektir.
Uygulamamızın kullanacağı referans edilmiş assembly bilgileri assemblynin manifest bölümünde saklanır.
Bunu en kolay IL Disassembler aracı ile görebilmemize karşın makalenin ilerleyen konularında da kullanacağımız
herhangi bir .NET Assemblynin tüm metadata ve IL bilgilerine erişip değiştirebilmeye yarayan CFF Explorer aracını kullanmanızı
tavsiye ederim.
waHavale.exe uygulamasını CFF Explorer açtığımızda sol tarafdaki ağaçta bu assemblynın PE başlık bilgileri gibi birçok detaylı bilgiye
erişmenin yanında bizim için asıl önem taşıyan .NET Directory bölümüdür. Bu kısımda assembly ile ilgili tüm metadata bilgilerini açıkça
görebilmekteyiz.Bu kısımları bu makalemizde konudan uzaklaşmamak için çok fazla detaylandırmak istemiyorum. Ama bir assemblynin genel olarak
hangi bölümlerden oluştuğunu görebilmek için için aşağıdakı resim yeterli olacaktır.
(Umarım ileriki makalelerde bir .net assemblysinin çok detaylı olarak yapısından
bahsedebiliriz.)
CFF Explorer da yukardaki şekilde görülen bir assemblye ait tüm bilgileri bize gösterebilmektedir.Ağaçdaki
.NET Directory -> Metadata Streams ->#~ kısmını açtığınızda Tables isimli
kısım assembly içerisindeki metadata içerisinde saklanan tüm tablo bilgilerini
vermektedir. Bu bilgileri kullanarak o assembly'nin içerisinde tanımlı tüm
metod, referans, sınıflar, üye elemanları vs gibi onlarca bilgiye
erişebiliyoruz.Kısaca araçdan bahsettikden sonra aşağıdaki resimde de görüldüğü
gibi uygulamamız beş adet referans kullanmakta ve bunlardan birisi de bizim
havale yapmak için geliştirdiğimiz clHavale.dll olduğunu görüyoruz.
Görüldüğü üzere referans olarak eklenmiş dllimiz hakkında tüm bilgi major,minor gibi versiyon bilgileri
kültür bigileri, ad vs gibi çok özel olmaya bilgilerdir.Yine Tables bilgilerinden yola çıkarak uygulamamız dllimizin içerisindeki
HavaleYap metoduna nasıl eriştiğini inceleyerek kendi yazacağımız sahte
bir dll'in uygulama tarafından sorunsuz nasıl çalıştırılabileceğini bulmaya
çalışalım. Öncelikle Tables-> MemberRef sekmesinde referans edilmiş üye elemanların listesine bakalım.33. sırada HavaleYap isimli metodun olduğunu göreceğiz.
Bu metoda tıkladığımızda hemen yanında açılacak olan bölümde Class bilgisinde TypeRef bölümündeki 38 sıradaki
type bilgisine yönelendiğini görüyüroz. TypeRef bölümüne baktığımızda 38. sırada Havale isimli sınıfımızın olduğunu buna tıkladığımızda da yanda açılan bilgiler kısmının ResolutionScope
bölümünde AssemblyRef bölümüdeki 4. sıradakı assembly'yı işaret ettiğini
göreceğiz. 4. sırada da clHavale.dll olduğunu yukardaki resimde görebiliyoruz.
Şimdiye kadar ki bilgilere baktığımızda
yazacağımız sahte dllin bu bilgiler çerçevesinde sorunsuz çalışacağını tahmin
ediyoruz.Hemen aynı isimli bir sınıf ve aynı isimli metodu içerecek bir dll
projesı oluşturup derledikten sonra oluşan assemblyyi orjinal olanı ile değiştirip uygulamamızın çalışıp çalışmadığını test edelim.
Sahte dllimizin kodu aşağıdaki gibi olsun.
public class Havale
{
public bool HavaleYap(int Kimden, int Kime, int Miktar,string sifre)
{
if (sifre.Equals("123")) //
Sifre 123 disinda bir deger ise kodumuz calisacaktir
{
return false;
}
int kesilenPara = 0;
if (Onayla(Kimden))
{
MessageBox.Show("Sahte Dll Ile Havale Yapiyorum!");
//kesilenPara = (int)(Miktar * 0.1);
//Para Kesilmesin :)
//havale islemleri yapilmistir!
return true;
}
else
{
return false;
}
}
private bool Onayla(int Kimden)
{
//musteri bilgileri kontrol edildi
return true;
}
}
|
Şimdi waHavale.exe ile aynı klasörde bulunan orjinal clHavele.dlli silip (ya da
baska bir isim verip) hazırladığımız sahte clHavale.dlli
kopyaladıkdan sonra uygulamamızı çalıştıralım. Daha sonra textboxa istediğimiz
( 123 dışında, umarım şifre tutturma gücünüz bu kadar yüksek değildir ) bir
değeri girip havale yapmak istediğimizde sonuç aşağıdaki gibi olacaktır.
Bu senaryoda görüldüğü gibi aslında istenmeyen bir durum oluşmuş uygulamamızın kullandığu harici müdahaleler ile
uygulamamızın istenemeyen şekilde çalıştırılması sağlanmıştır. Çünkü uygulamamız beklediği ve
derlendiğinde metadata bilgilerine yazılan (yukarda detaylı incelediğimiz
AssemblyRef, TypeRef ...) tüm bilgileri çalışma zamanında yüklediği sahte
clHavale.dll içerisinde de bulmuştur.
Senaryo 2
Önceki senaryomuzda
yeni bir dll yazılarak orjinali ile değiştirebildik. Değiştirilmesi planlanan
dll büyük ve yenisinin yazılmasının zahmetli olduğu durumlarda ne
yapabileceğimizi düşündüğümüzde bizim için önemli olan kritik kodları tespit etmemiz ve
çalışmasını değiştirmek ya da çalışmasına dokunmadan kod eklemek isteyebiliriz.Kod
eklemek isteyebilir miyiz ?
Evet var olan bir assemblyyi açıp havale yap metodunu bulup bunun içerisine istediğimiz kodu ekleyip ya da çıkarabilir,
sonra bu değişen assemblyyi kaydedip sanki hiçbirşey olmamış gibi (bu sanki
ilgili assemblynin kaynak kodları bizdeymiş ve biz projeyi açıp kaynak kodları
değitirip derledikden sonra yine aynı dlli elde ettiğimiz durumun aynısıdır.) uygulamayı çalıştırmaya devam edebiliriz.
Bu işleme kod gömme (code injection) denir.
Bu işlem için en iyi uygulamalardan birisi olan Reflexili kullanacağız.
http://sebastien.lebreton.free.fr/reflexil/ adresten araç ile ilgili
detaylı bilgi edinebilir ve
http://sourceforge.net/project/showfiles.php?group_id=200895&package_id=238891
adresinden de uygulamayı
indirebilirisiniz. Uygulama aslında mono da birçok projede kullanılan CeCil
altyapısını kullanarak, Reflector isimli decompiler aracına eklenti (plugin)
şeklinde tasarlanarak geliştirilmiştir.Reflexil'i indirdikten sonra zipli dosya
içerisindeki reflexil.dll'i Reflector uygulamasına plug'in olarak
kurabiliyoruz. ilk defa Reflector'e plugin ekleyecekler için gerekli adımları
gösteren resim aşağıdadır.
Bu işlemi de tamamladıkdan sonra artık uygulama ile birlikte gelen
clHavale.dll'i Reflector ile açabiliriz.Plugin'i ekledikten sonra Reflector
ile uygulamamızı açıp, HavaleYap metodunu disassemble ettiğimizde. Reflector'un
Tools menüsünden az önce exlediğimiz Reflex'il plug-in nin aktifleştiğini
göreceğiz.Buna tıkladığımızda ise hemen alt kısımda ilgili kodların IL
karşılığını görebiliriz.Bu kısıma sağ tıkladığınızda açılan menüden editleme,
silme ve kod ekeleme işlemlerinin yapılabildiğini görebiliriz.
Aslında burda editleme işlemi için iyi bir IL bilgisi gerektiğini görmekteyiz.
IL ile kod yazabilenler bu kısımın oldukça kullanışlı olduğunu, opcode'ların
tamamının hazır olarak geldiğini göreceklerdir. Ama IL ile uğraşmadan C# ya da
VB.NET ile kod yazarak assembly'yi değiştirmek isteyenler için menüdeki "Replace
all with code" menüsü oldukça kolaylık sağlayacaktır. Bu menüye tıkladığımızda haricibir editor açılacaktır.
C# kodu yazabilceğimiz bu editörde o anda kayank kodunu değiştirmek istediğimiz metodu görebilir ve içerisine
IL ile uğraşmada çalışmasını istediğimiz kodu yazabiliriz. Bu senaryodaki
amacımız şifre doğrulamasından kurtulmak olduğunu düşünürsek tek yapamamız
gereken şifre doğrulama kısmındakı kodu değiştirmek olacaktır (kod
silebileceğimizi göstermek adına da örnek koddaki kesilen para hesaplama kısmı
da koddan kaldırılmıştır).Bu durumda Reflector'ün ürettiği metodun kodlarını
kopyalayıp açılan editörde metodun içine yapıştırmak ve ilgili kod yerini
değiştirmek olacaktır.Aşağıdaki gibi kopyaladığımız kodu metodun içine
kopyaladıkdan sonra istediğimiz değişiklik ve eklemeleri yaptık.Sol alt
kısımdakı "Preview IL" butonuna tıkladıkdan sonra Sağ alt kısımdakı Ok butonu
aktifleşecektir. Ok dedikten sonra Reflexil yeni kodlarımızı orjinal
clHavale.dll 'in içine gömmüştür.
Bu adımlardan sonra havale işlemi yapacak olan bizim tarafımızdan içerisine kod gömdüğümüz (ve sildiğimiz)
Dllin diske kaydedilmesi gerekmektedir. Reflexil eklentisi aktifken Reflectorde üzerinde değişiklik yaptığımız
Dlli seçtiğimizde Reflexil bize uygulamayı kaydedip kaydetmeyeceğimizi sormaktadır.Bu adımda "Save as..." diyerek
orjinal Dllin üzerine kaydettiğimizde artık ana uygulama (Senaryo 1 deki bilgileri tekrar hatırlayın) sorunsuz bir
şekilde kodları değişmiş dlli sorunsuz bir şekilde çalıştırmaya devam edecektir.
Sonuç olarak geliştirilen bir uygulamaya dışardan kod gömülebilmekte veya
uygulamanın kullandığı dll'ler sahteleri ile değiştirilerek istenmeyen kodlar
çalıştırılabilmektedir. Bir sonraki
makalemizde bu durumları engellemek için neler yapabiliriz, uygulamamızın
dağıtım aşamasından sonraki senaryoları dikkate alarak ne gibi önlemler
alabiliriz gibi konulara değinmeye çalışacağız.
Makale kullanılan örnek uygulamaları indirmek için tıkayınız.
Oğuz YAĞMUR
MVP
[email protected]
Makale:
.NET ve Uygulama Güvenliği - 1 C#, Visual C# ve .NET Oğuz Yağmur
|
|
|
-
-
Eklenen Son 10
-
Bu Konuda Geçmiş 10
Bu Konuda Yazılmış Yazılmış 10 Makale Yükleniyor
Son Eklenen 10 Makale Yükleniyor
Bu Konuda Yazılmış Geçmiş Makaleler Yükleniyor
|
|