12

HZR

2010

web.config Dosyası, Önemli Alanları ve Şifrelenmesi

Yazan: Barış Samancı
Kategoriler:ASP.net

web.config dosyası üzerine bilgi internette yokmu? Var ama parça parça ve yetersiz olduğunu düşündüğüm için hem size kaynak hemde bana not oluşturması bakımından parmakları sıvadım :) Bu yazıda web.config dosyasının çok kullanılan alanlarını ve güvenlik için nasıl şifreleneceğini anlatacağım. Bu mesajı okuduğunuza göre web.config dosyasının ne olduğunu zaten biliyorsunuzdur. Uzun uzadıya ne olduğunu yazmayacağım fakat kısa bir bilgi verelim.

Web.config dosyası web sitesinin ortak konfigürasyon ayarlarının tutulduğu XML tabanlı bir dosyadır.Bu dosya sistenin kök dizininde olabileceği gibi belli dizinler altındada olabilir. Sitenin kök dizininde olduğunda dosyadaki bilgiler tüm siteyi etkiler, eğer bir dizin altına yerleştirmişsek dosyadaki bilgiler sadece o dizin altındaki sayfaları etkileyecektir.Buna örnek olarak üyelik sayfalarının içinde barındığı bir dizini verebiliriz. web.config dosyasında üyelik sayfalarının içinde bulunduğu dizin için kullanıcı girişi yapılmasını istediğimizde bu dizindeki sayfalara erişebilmek için yine web.config dosyasında belirttiğimiz kullanıcı adı/ parola çiftine sahip olan kullanıcılar istenilen sayfalara erişebilmektedir.

Web.config dosyası genelde sitenin ortak bilgilerini düzenler.Bu bilgilere örnek olarak veritabanı bağlantısı kurmak için kullandığımız connectionstring leri verebiliriz.Connectionstring leri kod dosyaları içinde ayrı ayrı yazmaktansa kolay erişilebilir olan web.config dosyası içerisine listelersek hem gerektiğinde hızlı bir şekilde değiştirebiliriz hemde daha düzenli, verimli bir yapı elde etmiş oluruz. Aynı şekilde sitemizin mail ayarları, sitemizde kullandığımız dll lerin referans bilgileri, sitemizin dil ve kültür bilgilerini, kullanıcı bilgilerini, kullanıcı tanımlı hata sayfalarını bu dosyada tanımlayabiliriz. Şimdi bu bilgilerden sık kullanılanların ne olduğu ve nasıl yazdıldığına bir göz atalım.Daha sonrada güvenlik için nasıl şifrelendiğine göz atalım. Aşağıdaki tüm düğümler configuration düğümü altına eklenmelidir.

Globalization

Sitemizdeki bazı asp.net kontrolleri encode ve decode işlemleri gerçekleştirmektedir.Aynı zamanda HttpServerUtility türünden Server nesnesinin HtmlEncode,HtmlDecode, UrlEncode,UrlDecode gibi kullandığımız bir çok metodu vardır.Bu metodlar sunucunun diline göre encode decode işlemleri yapmaktadırlar ve sayfalarımızı yabancı bir sunucuda barındırıyorsak Türkçe karakterlerde sıkıntı yaşayabiliriz.Bu sıkıntıyı web.config altında bir tanımlama yaparak çözebiliriz. Bunun için system.web düğümü altına aşağıdaki gibi globalization bildirimini yapmamız gerekmektedir.

 
<system.web>
      <globalizationresponseEncoding="windows-1254"fileEncoding="windows-1254"requestEncoding="windows-1254"culture="tr-TR"uiCulture="tr-TR"/>
</system.web>

Aynı şekilde yukarıdaki encodingler için Türkçenin içinde bulunduğu “iso-8859-9” yada “utf-8” karakter setlerinide kullanabilirsiniz.

 

connectionStrings

Sitemizde yaptığımız veritabanı bağlantıları için kullanacağımız connectionstring leri web.config altına eklemek derli toplu bir yapı elde etmemize yarar.Gerektiğinde değiştirmesi daha kolay olur ve tüm sayfalardan erişilebilir hale gelir.Bunun için configuration düğümü altına connectionStrings düğümü açıp altına aşağıdaki gibi kullanacağımız connectionstring leri eklememiz gerekmektedir.

      <connectionStrings>
    <addname="CONSTR_ADI"connectionString="Data Source=VERI-KAYNAGI;Initial Catalog=VERITABANI_ADI;Integrated Security=True"providerName="System.Data.SqlClient"/>
      </connectionStrings>

 

Bu şekilde add ile istediğimiz connectionstringleri uygulamamıza ekleyebiliriz. Yukarıdaki bildirimde ismi CONSTR_ADI olarak bildirdiğimize dikkat edin.Şimdi bu isimdeki connectionstringe kod dosyalarımızdan nasıl erişileceğine bakalım.

using System.Configuration; referansını kod dosyamıza ekledikten sonra
string constr = ConfigurationManager.ConnectionStrings["CONSTR_ADI"].ToString();

şeklinde connectionstringi çok rahat bir şekilde istediğimiz kod dosyasından okuyabiliyoruz.

 

mailSettings

Connectionstrings te olduğu gibi mail ayarlarınıda web.configte tanımlamak bize kolaylık sağlayacaktır ve bu ayarlar tüm uygulamadan erişilebilir hale gelecektir. Bunun için web.config dosyamızda configuration altına aşağıdaki kodları eklememiz gerekmektedir.

 <system.net>
    <mailSettings>
      <smtpfrom="user@domain.com">
        <network
          host="smtp.domain.com"
          port="587"
          userName="user@domain.com"     
          password="şifreniz"
          defaultCredentials="false" />
      </smtp>
    </mailSettings>
 </system.net>

Bu ayarları kod dosyalarımız dan using System.Net.Mail; referansını ekledikten sonra aşağıdaki gibi kullanabiliriz.

        MailMessage mail = new MailMessage();
        mail.IsBodyHtml = true;
        mail.From = new MailAddress("user@domain.com", "Barış Samancı");
        mail.To.Add(new MailAddress(aliciMail, aliciAdi));
        mail.Body = mesaj;
        mail.Subject = konu;
 
        SmtpClient smtp = new SmtpClient();
        smtp.Send(mail);
 

TTNET dahil bir çok ISP dünyada spam mailleri engellemek için ortak bir karar alıp standart olan 25 nolu SMTP portunu kullanmayıp 485 ve 587 gibi port numaraları kullanmaktadır.Uygulamanızda 25 numaralı porttan mail gönderemiyorsanız buna dikkat ediniz. 485 numaralı port SSL bağlantısı gerektirir.Bunun için smtp.EnableSsl = true; yazabilirsiniz.

 

Authentication

Web uygulamaları standart olarak bütün kullanıcılara açıktır. Fakat bazı bölümlerine sadece giriş izni olan kullanıcıların yada yöneticilerin girebilmesini isteriz.Bunun içinde web.config dosyasında bazı ayarlar yapmamız gerekmektedir.Aynı şekilde küçük uygulamalar için kullanıcıların kullanıcı adı ve şifre bilgilerinide web.config alanında bildirebiliriz.Forum siteleri gibi daha kapsamlı uygulamalar için veri tabanı kullanılmaktadır.Örneğin uyeler adında bir dizinimiz olsun ve bu dizin altındaki sayfaları görüntüleyebilmek için form tabanlı giriş yapılması istensin.

            <authenticationmode="Forms">
                  <formsloginUrl="login.aspx"timeout="60">
                        <credentialspasswordFormat="MD5">
                             <username="adminpassword="95c6e6873a1ac44779e6f8a32c7375fb"/>
                        </credentials>
                  </forms>
            </authentication>
 
            <authorization>
                  <allowusers="*"/>
            </authorization>

Yukarıdaki kodda “mode” ile kimlik doğrulamasının form tabanlı yapılacağı belirtilmiştir.Ve aşağıda belirteceğimiz uyeler dizini altındaki sayfalara erişmek istediğimizde ise kullanıcının giriş formunun yer aldığı login.aspx sayfasına yönlendirileceği loginUrl ile belirtilmiştir.Timeout ile giriş yapmış kullanıcıların herhangi bir işlem yapmadıkları taktirde 60 dakika sonra sistemden düşürülüp tekrar giriş yapması gerektiği bildirilmiştir. passwordFormat ile kullanıcı şifrelerinin MD5 ile şifrelenmiş bir şekilde saklandığı belirtilmiştir. Eğer herhangi bir şifreleme istemiyorsak buraya Clear yazmamız gerekir. Son olarakta user ile sisteme bir admin kullanıcı adına sahip bir kullanıcı eklenmiştir.Şifresi görüldüğü gibi MD5 ile şifrelenmiş bir biçimde tutulmaktadır.Yukarıdaki authorization altında belirtilen allowusers="*" bildirimi ile sitemizin kök dizininin tüm kullanıcılara açık olduğunu belirttik. * tüm kullanıcıları ifade etmektedir.

Şimdi sitemizin kök dizinine uyeler adında bir dizin açalım ve içerisine uye.aspx adında bir sayfa ekleyelim. Ardından aşağıdaki kodu web.config altına ekleyelim.

      <locationpath="uyeler">
            <system.web>     
                  <authorization>
                        <denyusers="?"/>
                        <allowusers="admin"/>
                  </authorization>
            </system.web>
      </location>

Görüldüğü gibi location ile uyeler adındaki dizin için ayar yapıyoruz.Bu ayarları yazının başında belirttiğimiz gibi uyeler dizini içinde ayrı bir web.config dosyası yaratarakta yapabilirdik. Location altındaki authorization ile bu dizin için kullanıcıların girişlerini ayarlıyoruz. denyusers="?" bildirimindeki ? işareti giriş yapmamış kullanıcıları temsil eder.Bu dizine giriş yapmamış olan tüm kullanıcıların erişimini engelliyoruz. Aynı şekilde allowusers="admin" ilede admin adındaki kullanıcının uyeler dizini altındaki sayfalara erişimine izin veriyoruz.Bu kodları yazıp uyeler dizini altındaki yaratmış olduğumuz uye.aspx dosyasına erişmeye kalktığımızda sistem otomatik olarak bizi loginUrl ile belirttiğimiz login.aspx sayfasına yönlendirecek.Şimdi bu sayfaya birisi kullanıcı adı için birisi şifre için iki adet TextBox  ve bir adet buton koyun.Sayfanın kod dosyasında butonun click eventine aşağıdaki kodu ekleyin.

        if (FormsAuthentication.Authenticate(txtKullaniciAdi.Text, txtSifre.Text))
            FormsAuthentication.RedirectFromLoginPage(txtKullaniciAdi.Text, true);

Eğer girmiş olduğunuz kullanıcı adı ve şifre doğru ise sizi login sayfasına yönlendirmiş olan sayfaya yönlendirileceksiniz.Bunu adres çubuğundaki querrystring ten görebilirsiniz.

 

CustomErrors

Web sitelerinde oluşan hataların kullanıcılara gösterilmesi hoş olmaz.Ayrıca varsayılan hatalarında işlenmemesi sonucu browserın verdiği hata mesajlarını görmekte hoş olmaz.Bu alanda sunucuda herhangi bir hata oluştuğunda yapılacaklar bildirilmektedir.Hata istemciye gösterilecekmi gösterilmeyecekmi yoksa bir hata oluştuğunda istem hata kodu ile ilgili sayfaya yönlendirilecekmi gibi bilgiler bu düğüm altında yer alır.Yazılması gerekenler aşağıda gözükmektedir.

<system.web>
<customErrorsmode="On">
            <errorstatusCode="404"redirect="404.htm"/>
            <errorstatusCode="500"redirect="500.htm"/>
</customErrors>
</system.web>

Yukarıda gözüken On nun anlamı oluşan hataları istemciye göstermedir.Bu sayede hata oluştugunda nerede hangi satırda hata oluştuğu ve hata oluşturan kodlar istemcilere gösterilmez.Bu alanı Off yaparsak oluşan hatalar istemciye gösterilir.Bu alan ayrıca RemoteOnly de olabilir ve bu sistem varsayılanıdır.Bunun anlamı sunucudaki sayfalar çalışırken oluşan hataları internet üzerindeki istemcilere gösterme, localdeki istemcilere gösterdir.

İlgili hata ile ilgili error bilgisini yukarıdaki gibi eklersek istemciler bir hata oluştuğunda daha önceden hazırladığımız ilgili hata sayfalarına yönlendirileceklerdir.Yukarıdaki örnekte 404 sayfa bulunamadı hatası oluştugunda istemci 404.htm sayfasına, 500 sunucu hatası oluştuğunda ise 500.htm sayfasına yönlendirileceklerdir.

 

Bilgileri Şifreleme

web.config dosyasının XML tabanlı bir txt dosyası olduğunu yazının başında söylemiştik.Bu nedenle web.config dosyamızı eline geçiren kötü niyetli bir kişi bu dosyadaki şifrelerimizi açıkça görebilir.Bunun için bir şifreleme mekanizması geliştirilmiştir. Bu mekanizma ile web.config dosyamızdaki açıkça gözüken connectionstring, mail veya kullanıcı bilgileri alanlarını şifreleyebilmekteyiz.İşin güzel yanı bu bilgiler web.config dosyasında bir kere şifrelendikten sonra şifreli bir halde tutulurken çalışma zamanında otomatik olarak decode edilip kullanılırlar.

Şifrelemeyi iki türlü yapabiliriz.Birincisi aspnet_regiis exesini kullanmak ikinci olarakta yazdığımız bir kod ile herhangi bir sayfadan şifrelemektir.Şimdi bunları sırası ile inceleyelim.

aspnet_regiis.exe dosyası “C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727” dizini altında bulunmaktadır.Şimdi bu exeyi kullanarak connectionString alanını şifreleyelim.Kullanacağımız syntax aspnet_regiis -pe "ŞifrelenecekAlan" -app "/SiteninVirtualAdı" –prov “Provider” şeklindedir. Burada şifrelenecek dosya local IIS de sitemizin sanal dizinindeki web.config dosyasıdır.Bunu –pe parametresinden anlıyoruz. Eğer local IIS yerine Visual Studio nun kullandığı fiziksel dizinindeki dosyayı şifrelemek isteseydik –pef kullanıp “/SiteninVirtualAdı” alanına fiziksel yolu yazmamız gerekecekti.Diğer dikkat etmemiz gereken şifreleme provider ıdır bunuda –prov paramatresinde belirtiyoruz.Kullanabileceğimiz providerler aşağıdaki gibidir.

RSAProtectedConfigurationProvider
DataProtectionConfigurationProvider

Şimdi komut satırını açıp anlatılanları yapalım.Provider olarak DataProtectionConfigurationProvider kullandığımızı varsayalım.Komut satırına yazmamız gereken aşağıdaki gibidir.

aspnet_regiis -pe "connectionStrings" -app "/barissamanci.net" -p>İşlem başarı ile tamamlandığında aşağıdaki gibi bir görüntü ile karşılaşırız.

web.config sifreleme

web.config dosyamıza baktığımızda connectionStrings alanının aşağıdaki gibi şifrelendiğini görürüz.

<connectionStringsconfigProtectionProvider="DataProtectionConfigurationProvider">
 <EncryptedData>
   <CipherData>
    <CipherValue>AQAAANCM....qA7K60=</CipherValue>
   </CipherData>
 </EncryptedData>
 </connectionStrings>

Bahsettiğimiz gibi bu şifrelenmiş veri çalışma zamanında çözülerek kullanılmaktadır.Yukarıdaki ConnectionStrings başlığı altında anlattığım gibi kod dosyalarınızdan kullanabilirsiniz.Eğer mail alanını şifrelemek isteseydik şifrelenecek alan kısmına system.net/mailSettings/smtp yazmamız gerekecekti.Aynı şekilde üyelerin kullanıcı adı ve şifrelerini encrypt etmek istesek şifrelenecek alan kısmına system.web/authentication yazmamız gerekecekti.İlgili alanları kontrol ettiğinizde connectionstrings örneğine benzer bir şekilde şifrelendiğini göreceksiniz.

Peki bu bilgileri şifreledik nasıl geri alağız derseniz bende size –pe yi –pd olarak değiştirin diyeceğim :) örnek olarak

aspnet_regiis -pd "connectionStrings" -app "/barissamanci.net" -prov "DataProtectionConfigurationProvider"
 

Bu yöntemi local IIS nizde kullanabilirsiniz.Fakat makinaların şifreleme anahtarları farklı olacağından şifrelenmiş dosyanızı sunucuya attığınızda aşağıdaki hata mesajı ile karşılaşırsınız.

Configuration Error
Description: An error occurred during the processing of a configuration file required to service this request. Please review the specific error details below and modify your configuration file appropriately.

Parser Error Message: Failed to decrypt using provider 'DataProtectionConfigurationProvider'. Error message from the provider: Key not valid for use in specified state. (Exception from HRESULT: 0x8009000B)
 

Peki sunucudaki web.config dosyasını nasıl şifreleyeceğiz dediğinizi duyar gibiyim :) Bunuda sunucuda kod yazıp yapacağız.Aşağıdaki metodları kullanarak istediğiniz alanı istediğiniz provider ile şifreleyip şifresini çözebilirsiniz.

 
    public void Sifrele(string alanAdi, string provider)
    {
        Configuration config = WebConfigurationManager.OpenWebConfiguration(Request.ApplicationPath);
 
        if (config == null)
            return;
        ConfigurationSection alan = config.GetSection(alanAdi);
        if (alan == null)
            return;
        if (!alan.SectionInformation.IsProtected)
        {
            alan.SectionInformation.ProtectSection(provider);
            config.Save();
        }
    }
 
    public void SifreCoz(string alanAdi)
    {
        Configuration config = WebConfigurationManager.OpenWebConfiguration(Request.ApplicationPath);
        if (config == null)
            return;
 
        ConfigurationSection alan = config.GetSection(alanAdi);
        if (alan == null)
            return;
 
        if (alan.SectionInformation.IsProtected)
        {
            alan.SectionInformation.UnprotectSection();
            config.Save();
        }
    }
 
 

Bu metodları projenize ekledikten sonra aşağıdaki şekilde kullanabilirsiniz.

Sifrele("connectionStrings", "DataProtectionConfigurationProvider");
SifreCoz("connectionStrings");
 

Yanlız dikkat etmeniz gereken sunucular varsayılan olarak yazma iznini kapalı tutarlar.Eğer sunucunuzdaki web.config dizinine yazma kapalı ise yukarıdaki kodlar hata verir.Klasör izinlerini değiştirerek bu sorunu çözebilirsiniz.Yanlız işinizi bitirdikten sonra kök dizin için yazma iznini tekrar kaldırmayı unutmayın.Eğer kök dizine yazma izni veremiyorsanız web.config dosyasındaki alanları yazma izni verebildiğiniz bir dizin altına yeni bir web.config dosyası açarak içerisine kopyalayıp şifreleyebilirsiniz.Şifrelendikten sonra ana web.config alanına şifrelenmiş bilgileri taşıyabilirsiniz.

Şifreleme hakkında daha detaylı bilgi istiyorsanız http://msdn.microsoft.com/en-us/library/ms998283.aspx linkini ziyaret edebilirsiniz. Siz yazıyı okurken ben bir kahve molası vereyim.Bu yazıdan sonra baya ihtiyacım var :)

 

 

Yorumlar
Vedat
11 Mar 2016 Cuma, 14:36 tarihinde yazmış.

Hocam emeğinize sağlık çok güzel bir yazı.Asp.nette site güvenliği ile ilgili biraz araştırma yaptım.Genelde web.configle ilgili düzenlemeler,uploadta dosya uzantısı kontrolü,sql injection vb anlatılmış.Eğer siteye saldırı sunucu içinde kötü niyetli bir çalışandan gelirse bu gibi durumlarda neler yapılabilir?Aklıma ilk gelen kodları .cs yerine dll de saklamak,obfuscator kullanımı,web servisle şifreleri sunucular arasında dağıtmak vb.Bu konuda sizin önerileriniz nedir acaba?Teşekkür ederim.

12 Mar 2016 Cumartesi, 16:32 tarihinde yazmış.

Merhaba, uzantı kontrol etmek yetmeyebilir. Dosyaların ilk verileri imzalarıdır. Örneğin exeyi incelersen ilk iki harfinin MZ, png dosyasını incelersen PNG görürsün. Uzantısı png olan çalıştırılabilir zararlıda olabilir. SQL injection için SQLParameter sınıfını kullanabilirsin. Kullanıcının giriş yapabileceği tüm alanlarda (querystring, textbox vs) kontrol yapmalısın. obfuscator türevlerini ben kullanmıyorum. Sunucudada kodlarını dll olarak kullan, webconfigide şifrele. Açık kod şifre kullanma

Vedat
14 Mar 2016 Pazartesi, 09:21 tarihinde yazmış.

Tavsiyeleriniz için çok teşekkür ederim Barış hocam.Güvenlik konusu gerçekten önemli,yoksa emek kaybı,zaman kaybı vb durumlar olabilir.Çalışmalarınızda başarılar dilerim,kolay gelsin.

Adınız *:
e-Mail Adresiniz *:  ??
Web Siteniz:
Yorumunuz *:
Kalan karakter sayısı: 500
 
 

Tasarım ve Programlama Barış SAMANCI
Her hakkı saklıdır.
barissamanci.net  ©  2010-2024