Bu site emekli olmuştur. Arşiv amaçlı olarak BT AKADEMİ sponsorluğunda yayın hayatına devam etmektedir.




C#nedir?com
 
YAZAR HAKKINDA
Oğuz Yağmur
Oğuz Yağmur
http://www.oguzyagmur.com
İletişme geçmek için tıklayın.
26 Makalesi yayınlanmakta.
Yazar hakkında detaylı bilgi için tıklayın.
Yayınlanan diğer makaleleri için tıklayın.
İlgili etiketler: anahtar assembly degeri degerini durumda height: isimli kisaca kullanilarak private public sifreleme sifrelenmis sonucunda uygulama C# / VC#/.NET Oğuz Yağmur
 
YAZI HAKKINDA
Türü : Makale
Serbest Köşede C#nedir?com üyelerinin hazırladıkları yazılar yayınlanır. Bu yazılar editör incelemesine girmeden yayınlanır.
Seviyesi : İleri
Kategori : C# / VC#/.NET
Yayınlanma Tarihi : 21.1.2009
Okunma Sayısı : 66841
Yorum Sayısı : 1     yorum yaz
Site İçi AramaSİTE İÇİ ARAMA
Üye Girişini AçÜye GİRİŞİ
Üye girişi için tıklayın.
Kullanıcı Adı
Şifre
 
Beni her zaman hatırla
Bir hafta boyunca kullanıcı bilgilerinizi kullanıcı çıkışı yapana kadar hatırlar. (Paylaşılan bilgisayarlarda önerilmez.)
 
Şifremi / Kullanıcı Adımı unuttum.
 
.net TV RSS Serbest KÖŞE (?)
Serbest Köşede C#nedir?com üyelerinin hazırladıkları yazılar yayınlanır. Bu yazılar editör incelemesine girmeden yayınlanır.
emre TAŞ
Silindi
emre TAŞ
yazının devamı >
emre TAŞ
silindi
emre TAŞ
yazının devamı >
emre TAŞ
silindi
emre TAŞ
yazının devamı >
emre TAŞ
silindi
emre TAŞ
yazının devamı >
emre TAŞ
silindi
emre TAŞ
yazının devamı >
Makale Gönder Bende Yazmak İstiyorum
.net TV RSSBlogroll
Turhal Temizer
Conda install environment.yml Package 19.4.2024
Turhal Temizer
Mac OS/X Removing CUDA 19.4.2024
Burak Selim Şenyurt
Kurumsal Yazılımcının Oyun Geliştirme ile İmtihanı 19.4.2024
Burak Selim Şenyurt
Matematik ve Oyun Programlama - Missile Command - Final 19.4.2024
  Diğer Herşey
Sponsorlar
BT Akademi
Medya Portakal
Video Hosting Sponsoru
Csharpnedir.com bir Ineta üyesidir
Uzman Abi
Her Yönüyle C# - Sefer Algan
.NET ve Uygulama Güvenliği - 2
 
Kapat
Sayfayı Yazdır Sık Kullanılanlara Ekle Arkadaşıma Gönder MySpace Del.Ico.Us Digg Facebook Google Mixx Reddit StumbleUpon
Daha önceki makalemizde (.NET ve Uygulama Güvenliği 1) dağıtım aşamasından sonra uygulamamız üzerinde istemediğimiz şekilde değilik yapılmaya müsait olabildiğini inceledik. Bu makalemizde iste bu tür sorunlara karşı neler yapılabileceğini Microsoft’un araçları ile ya da 3. parti araçlar ile ne gibi önlemler alabileceğimizi inceleyeceğiz. Kısaca önceki senaryolardan bahsedecek olursak, uygulamanın dağıtımından sonraki safhada, uygulamamız ya da uygulamanın kullandığı Dll’ler Reflector ile açılıp kodlar görüntülendikten sonra (Type bilgileri ve isimleri çözüldükten sonra) benzer bilgiler ve isimlerden yola çıkılarak orjinallerinden farklı Dll'ler oluşturulup, orjinalleri ile değiştirilerek farklı ya da zararlı kodların çalıştırılabilmesi sağlanmaktadır. Diğer bir senaryomuzda ise, yeniden yazılamayacak kadar karmaşık veya yazılmasına gerek kalmadan sadece belirli bir metodun veya kod bloğunun değişmesi sonucunda uygulama amacından farklı çalışması sağlanarak istenmeyen durumlara neden olabildiğini ve bunun da uygulama ya da uygulamanın kullandığı Dll’lere kod gömerek (code injection)nasıl gerçekleştirilebileceğini incelemiştik.

Dijital Imzalama

Daha önce az çok .NET üzerinde uygulama geliştirenler tekil isim (strong name) kavramı ile karşılaşmışlardır. Geliştirilen assembly'lerin güveliğini sağlamak, tekilliğini belirtmek, versiyonlamak, Com+ kullanmak  veya geliştirilen assembly'nin GAC'a yüklenmesi gerektiğinde assembly'lerimizin tekil isme sahip olmaları gerekmektedir. Tekil isim "BTA.CoreDevelopment.Client.dll" şeklinde assembly adı değil , "assembly adı + versiyon numarası + culture bilgisi ve public key token" bilgilerinin birleşimi sonucunda oluşur. Aslında çok kısa bir özetle tekil isim "bir assembly'nin tekilliğini sağlamak" amacı ile kullanılır. Bu tekilliği sağlamak için de tabiki sadece bize ait olan bazı bilgilerin olması gerekmektedir. Sadece bize özel olan bu bilgileri kullanarak assembly'yi işaretlenerek tekillik sağlanabilmektedir. Bunun için de günümüzde yoğun olarak kullanılan dijital imzalama (digital signature) yöntemini  tekilliği sağlamakta kullanabiliriz. Assembly'lerin tekilliğini nasıl sağlandığını anlayabilmemiz için öncelikle şifreleme tekniğini biraz inceleyelim.

Temel prensip olarak hashing ve public/private anahtarlar kullanılarak yapılan imzalar birlikte kullanılarak belirli bir veri için tekillik oluşturulabilir. Hashing'in mantığında belirli bir veri üzerinden kullanılan algoritmaya göre özel bir değer üretme söz konusudur.
 

Yukardaki şekilden de anlaşılacağı üzere hashing işlemine tabi tutulacak veri korumak istediğimiz assembly olduğunu düşünürsek, assembly üzerinden bir hash algoritması(MD5, SHA1 vsvs) ile bir değer elde edebiliriz. Eğer assembly içerisinde bir değişiklik olursa üretilecek olan Hash değeri de farklılaşacaktır. Hashing genelde şifreleme ile karıştırılan bir konudur.Hashing bir sıkıştırma ya da şifreleme yöntemi değildir. Sıkıştırma ya da şifrelemede orjinal veriyi tekrar elde etmek mümkün iken Hash değerinden yola çıkarak orjinal veri elde edilemez. Peki bu durumda hash değeri bizim için ne anlam ifade etmektedir ? Aynı hashing algoritması kullanılarak farklı iki assembly den elde edilen hashing değerlerine bakıldığında aynı sonucu elde etmiş isek bu iki assembly aynıdır diyebiliriz ki bu durumda hash değerleri karşılaştırma amacı ile ile kullanılır sonucunu çıkarabiliriz. Gerçekte de derleyici kod derlendikten sonra oluşan assembly'nin içerisine bu elde ettiği hash değerin yazmaktadır.



 Yukardaki resimde de görüldüğü gibi CFF Explorer (bir önceki makalede bu araçtan bahsetmiştik) ile bir assembly incelendiğinde SHA1 algoritmasi kullanılarak oluşturulan hash değerini görmüş oluyoruz. (MD5 algoritmasi kullanılarak da hash değerinin yazıldığını görüyoruz ki şu anda detay yapılacak konu değildir. CLI dökümanları incelendiğinde bu alanın ileriye yönelik kullanım amaçlı konulduğunu bilgisine erişilebilir) Bu açıklamalardan sonra akla gelecek ilk soru " bu alanı harici müdahaleler ile değiştiremez miyim ?" olacaktır. Cevap ise vahim : "evet değiştirilebilir". Bu durumda assembly'nin hash değeri ile üzerinde değişiklik yapılarak elde edilen  sahte assmebly'nin hash değerleri değiştirilebilir ve bu nedenle de tekillik güvenliğini sağlamamış oluruz.
Bu soruna çözüm olarak elde ettiğimiz bu hash değerini şifreleyerek assembly içerisine yazdığımızda dışardan müdahale etmek istendiğinde şifrelenmiş hash değeri ile karşılaşılacak ve bu hash değerinin gerçek değeri bilinmediğinden ilerleme kaydedilemeyecektir. Bu durumda assembly içerisine şifrelenerek yazılmış hash değerinin orjinal değerine erişmek için gerekli anahtarı da koymamız gerekmektedir. Aksi durumda karşılaştırma yapılmak istenildiğinde gerçek hash değerine ulaşılamayacağı için biz de sorun yaşıyor olacağız. İşte bu aşamalarda  public/private anahtar yöntemini kullanarak assembly içerisine hem şifrelenmiş hash değerini hem de şifreyi çözecek public anahtarı koyarak sorunumuzu halletmiş olacağız.Bu yöntemi kullanmadan önce public/private anahtarlar kullanılarak nasıl şifreleme yapılabildiğini kısaca inceleyelim.


Yukardaki resimde de açıkça görüldüğü gibi eğer bir veri public anahtar ile şifrelenmiş ise bunu ancak private anahtar ile, eğer veri private anahtar ile şifrelenir ise bunu anca public anahtar ile çözebiliriz (Konu hakkında detaylı bilgiler için Asimetrik Şifreleme konularına bakınız). Yani şifrelenmiş verinin orjinal halini görebilmek için ya private (public anahtar ile şifrelenmiş işe) ya da public ( private anahtar ile şifrelenmiş ise) anahtara sahip olunması gerekmektedir.

Hashleme ve asimetrik şifreleme yöntemleri kullanılarak oluşturulan assembly'lere tekil isim (strong name) verebilmekteyiz. Aşağıdaki resimde basit bir şekilde bu işlemin nasıl yapıldığı gösterilmektedir.


Yukardaki şekli kısaca özetlemek gerekirse, derleme sırasında oluşturulan assembly’den öncelikle SHA1 hash algoritmasi ile bir değer üretirlir. Bu değer assembly içerisine daha önce açıkladığımız gibi değiştirilme ihtimali göz önüne alınırak doğrudan yazılmaz. Oluşturulan private anahtar ile bu assembly'ye özel hash değeri şifrelenir ve  geri çözülebilmesi için public anahtar ile birlikte assembly içerisine kaydedilir.

Çalışma zamanında imzalı assembly'yi yükleyen birim assembly'den bir hash değeri üretir. Daha sonra assembly içerisindeki şifrelenmiş hash değerini public anahtar kullanarak gerçek hash değerini elde eder. Bu iki hash değerini karşılaştırdığında eğer aynı değerleri elde ediyor ise assembly doğrulanmış olur.

Şimdi bir tekil isme sahip assembly oluşturup bu assembly'yi önceki makalemizdeki gibi değiştirmeye çalışalım. Öncelikle yukardaki anlatılanlar doğrultusunda public/private anahtar ikilisine ihtiyaç vardır. Bu amaç için Sn.exe isimli aracı Visual Studio 2008 komut satırından aşağıdaki parametrelerle kullandığımzda bize public/private anahtar ikilisini üretecektir.

sn -k bta.snk (sn.exe -k dosyaismi)

Eğer üretiken bu anahtar ikilisinden sadece public anahtar dosyasını elde etmek istenildiğinde sn.exe aşağıdaki gibi kullanılabilir.

sn -p bta.snk btapublic.snk

Bir assembly'nin public anahtarı  ile ilgili bilgi almak için ise

sn -Tp bta.dll

şeklinde kullanılması yeterli olacaktır. Oluşturulan snk dosyası projeye eklenir ve projenin AssemblyInfo.cs dosyası içerisine aşağıdaki kod satırı eklenerek derleme işlemi sırasında tekil isim oluşturulması sağlanmış olur.

[assembly: AssemblyKeyFile("bta.snk")]

Visual Studio 2008 ile bilirlikte assembly'lerin kolay bir şekilde imzalanmasi için ek özellik getirildi. Projeye sağ tıkladıkdan sonra açılan menüden Properties menüsüne tıkladığımızda açılan ekranda Signing sekmesine tıkladığımızda Signing bölümünü göreceğiz. Eğer daha önceden bir dosya varsa bu kısımdan seçebilir ya da ilk defa oluşturulmak istenirse yine bu kısımdan yeni public/private anahtar dosyamızı oluşturabiliriz.



Anahtarı oluşturdukdan sonra Solution Explorer penceresiden uygulama dosyaları incelendiğinde *.pfx uzantılı bir dosyanın projeye eklendiğini görebiliriz.Artık bu assembly derlendiğinde şimdiye kadar bahsettiğimiz tekil isme sahip olacaktır. Oluşan assembly IL Disassembler ile açılıp manifest kısmına bakıldığında tekil isme sahip olmayan assembly'lerden farklı olarak artık public anahtarı içerdiğini görebilmekteyiz.



Şimdi önceki makalemizde geçen senaryoları tekil isim verilmiş bir assembly üzerinde gerçeklemeye çalışalım. Birinci senaryo da geçek assembly'nin Reflector ile açılarak kod yapısının tespit edilmesi ve benzer bir assembly geliştirilerek gerçeği ile değiştirilmesi sonucunda uygulamamızın istenemeyen kodları çalıştırması idi.Önceki makalemizdeki clHavale.dll uygulamasını bu defa yukardaki açıklamalar doğrultusunda *.pfx  dosyasını oluşturup tekil isim vererek derleyelim.


Bu adımdan sonra waHavale isimli pencere uygulamamıza bu tekil isim verilmiş dll'i referans ederek derleyelim. Daha sonra sahte dll ile bu tekil isime sahip dll'i değitirelim. Hatırlayacağınız üzere eğer bizim geliştirdiğimiz dll tekil isme sahip değildi ve uygulama bu harici müdahale sonucunda sorunsuz olarak çalışmıştı. Geliştirme aşamasında dll'i tekil isme sahip şekilde hazırladığımızda ise bu müdahale sonucu başarısız olacaktır.



Görüldüğü gibi tekil isme sahip bir dll’i kullanarak derlenen ana uygulamamız çalışma zamanında ilgili tekil isme sahip dll içerisindeki kodları kullanmak istediğinde ilgili dll’i yükleme çalışırken tekil isimli dll olup olmadığını kontrol etmekte, eğer bu tekil isimli dll’i bulamazsa da çalışma zamanında hata üretmektedir. Bu örnekteki tekil isim "clHavale, Version=1.0.0 ,Culture=neutral, PublicKeyToken=b0c1e38505bbbe10" dur. Daha öncede bahsettiğimiz gibi tekil isim için gerekli verilen isim içerisinde yer almıştır. PublicKeyToken assembly içerisine gömülen public anahtarımızdan üretilen hash değerinden ibarettir. Önceki makaledeki bilgilerden yola çıkarak , tekil isimli dll uygulamaya (exe) refere edildiğinde uygulama içerisinde bir yerlerde bu bilgi kaydedilmekte ve çalışma zamanında bu bilgi kontrol edilmektedir. (Bir önceki makalemizde açıkladığımız AssemblyRef kısmı olabilir mi ?) . Makalenin ilerleyen bölümünde bu kısmı detaylandıracağız.

Diğer senaryomuzda ise Reflector ve Reflexil araçları ile bir assembly'nin kodlarının değiştirilmesi işleminden sonra değişikliğin yine aynı assembly üzerine yazılması sonucunda uygulama istenemeyen kodlar ya da kodların silinip kaydedilmesinden sonra çalışması gereken kodların çalışmaması söz konusu idi.Aynı adımları tekil isme sahip clHavale.dll üzerinde yapmaya çalıştığımızda Reflexil bize aşağıdaki seçeneklerden hangisini uygulayacağını sormaktadır.



Görüldüğü gibi aslında kodları değiştirilmiş assembly doğrudan kaydedilememekte alternatif seçenekler sunmaktadır. Bu seçeneklere kısaca değinirsek;
Register it for verification skipping tercih edildiğinde Reflexil kodları değişmiş assembly’yi oluşturur ve ana uygulamamızın bu assembly'yi çalışma zamanındaki onaylama işlemine tabi tutmadan çalıştırabilmesi için kayıt defterine (registry) HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\StrongName\Verification  altında clHavale,B0C1E38505BBBE10 isimli (dikkat edeceğiniz gibi assembly adı ve assembly'nin PublicKeyToken bilgisi) bir anahtar oluşturmuştur.
Artık ana uygulama tekil isme sahip bu dll için çalışma zamanında yukarda bahsedilen hash değerlerinin aynı olması üzerine kurulu kontrol işlemini yapmayacaktır. Ve bu durumda da uygulama yine sorunsuz bir şekilde çalışmaya devam edecektir. (Ama kayıt defterine erişim hakkı bulunmayan kullanıcılar için bu seçenek işe yaramayacağından istenilen sonucu elde edememiş oluyoruz. )

Re-sign with key seçeneğinde ise Reflexil private anahtarı isteyerek değişmiş olan bu assembly için tekrar bir tekil isim oluşturma işlemi yapabileceğini söylemektedir. Oysaki geliştirici dışında kimsede private anahtar olmadığı için bu mümkün olmamaktadır. Eğer private anahtar bizde olsa idi Reflexil değişen asssembly için hash değeri üretecek bunu da private anahtar ile şifreledikten sonra assembly içerisine kaydedecek böylelikle ana uygulama rahatlıkla bu assembly'yi runtime da yükleyerek çalıştıracaktır.Yine eğer private anahtar bizde olsa idi dll'i yeniden yazdıkdan sonra kendimiz imzalayabilirdik.Bu nedenle private anahtarın gizliliği oldukça önemlidir.

Remove strong name seçeneği ise oldukça cüretkar imkanlar sunmaktadır. Kısaca assembly'nin imzasını assembly içinden silecek ve açılan pencerede ise bu assembly'ye referansda bulunan ana uygulamayı (tercihe göre) isteyerek ana uygulama içerisindeki tekil isme ait bilgileri yok edecektir. Bu aşamadan sonra ana uygulama bir önceki makalemizde detaylı bahsettiğimiz assembly bilgilerinden yola çıkarak değiştirilmiş assembly'yi çalıştırabilecektir. Aslında bu çok da karmaşık bir işlem değildir. Yani tekil isimli assembly'yi refere eden uyugulamayı CFF Explorer ile açıp metadata bilgilerinden AssemblyRef tablosundaki clHavale.dll 'in bilgilerine baktığımızda PublicKeyOrToken bilgisinin var olduğunu görürüz. İşte bu kısmı düzenleyerek 0 değerini verdikten sonra ana uygulama kaydedildiğinde sahte dll ile gerçek dll yer değiştirir. Bu adımdan sonra da ana uygulama tekil isme sahip olup olmadığına bakmadan ilgili dll'i yükleyebildiğini ve çalıştırdığını göreceğiz.



Bir başka senaryo da şu olabilir. Ana uygulama tekil isme sahip bir dll beklemektedir. Biz de tekil isme sahip dll'i açıp içerisine kod gömüp ya da sildikten sonra ana uygulama tarfından çalıştırılmasını istediğimizde ilk adım olarak yukardaki gibi ana uygulama içerisinde clHavale.dll ine ait PublicKeyOrToken bilgisini 0 yaparak ana uygulamayı kaydettik. Bu durumda hala gerçek dll'imiz tekil isme sahip olduğu için ana uygulama da tekil isme sahip olmayan bir dll aradığı için gerçek clHavale.dll çalıştırılamayacaktır. Bu durumda gerçek clHavale.dll den imza bilgisini silmemiz gerekmekte ve bunun için de yine CFF Explorer'dan faydalanarak aşağıdaki görüldüğü gibi PublicKey bilgisi 0 yapılarak tekil ismin yok edilmesi sağlanabilmektedir. Biraz araştırma yapıldığında tekil ismi silen birkaç uygulama olduğunu görebiliriz.



Cancel with Delay Signed seçeneği ise şu aşamada detaylandırma ihtiyacı duymadığımız bir konu. Kısaca delay signed geliştirilen dll'in içerisinde sadece public anahtarın bırakılarak private anahtar olmadan da kodu yazmak ve assembly'yi geliştirmek için gerekli imkanların sağlanmasına yaramaktadır. Assembly geliiştirildikten sonra dağıtım aşamasında private anahtar kullanılarak assembly imzalanır ve dağıtıma hazır duruma getirilir. Delay Singing  hakkında detaylı bilgi için http://msdn.microsoft.com/en-us/library/t07a3dye.aspx adresinden faydalanabilirisiniz.

Şu ana kadar bir assembly'nin imzalanması sonucunda eskisi kadar rahat bir şekilde harici müdahale edilemediğini ama hala bazı müdahaleler sonucunda yine istenmeyen durumların gerçekleşebiliceğini görmüş olduk. Aslında şu ana kadar bahsettiğimiz tüm konulardan çıkan tekil isim assembly'nin tekilliğini sağlayabilmekte ama uygulamanın güvenirliğini görüldüğü üzere  sağlayamamaktadır.

Makalede kullanılan örneği idirmek için tıklayınız.

Oğuz YAĞMUR
MVP
[email protected]

Makale:
.NET ve Uygulama Güvenliği - 2 C#, Visual C# ve .NET Oğuz Yağmur
  • Yazılan Yorumlar
  • Yorum Yaz
OCA
22
2009
Oğuz hocam bu güzel iki makale için çok teşekkürler. Makalede de görülüğü üzere güvenliği artırmamıza rağmen hala açıkların olması sıkıntı verici. Artı bir güvenlik katması için Kod karıştırıcı (dotfuscator v.b.) programları kullanmakta fayda var sanırım. Güvenlik konusuna da değindiğiniz için teşekkürler. Görüşmek üzere.
Sayfalar : 1 
Yorum yazabilmek için üye girişi yapmalısınız. Üye girişi için tıklayın.
Üye değilseniz Üyel Ol linkine tıklayarak üyeliğinizi hemen başlatabilirisniz.
 
  • Bu Konuda Son 10
  • 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