11 Haziran 2017

Güvenli Yazılım Geliştirmede Cross Site Scripting (XSS) Ve AntiXSS Kütüphanesi


Bu yazıda Cross Site Scripting yani daha çok kullandığımız ismiyle XSS üzerine konuşacağız.

Eski bir açıklıktır ve son Owasp Top 10'de de her zamanki gibi yerini almıştır. Kaynak kod analizlerinde veya sızma testlerinde de oldukça adını duyduğumuz bir açıklıktır.

XSS, bir saldırganın kaynak kod içerisine kendi zararlı kodlarını enjekte edebilmesini neden olan bir zafiyettir. Bu zafiyeti istismar eden bir saldırganın geniş yelpazede bir zarar vermesi mümkün olabilmektedir.

Üç çeşit XSS türü vardır. Bunlar arasındaki fark girdinin kullanıcıya ulaşma şekliyle alakalıdır, yani istismar etmenin zorluğuyla, etkisi ile değil:
  1. Stored XSS çeşidinde; zararlı kod veri tabanına depolanmakta, ilgili sayfa her çağrıldığı zaman bu kod çalışmaktadır. 
  2. Reflected XSS çeşidinde; zararlı kod sunucuya gitmekte, sunucudan doğru şekilde sanitize edilmeden geri dönmektedir. Örneğin URL'de bulunan bir parametredeki zafiyeti istismar etmek isteyen bir saldırgan, hazırlayacağı zararlı kod barındıran URL'i seçtiği kullanıcıya göndererek bu kullanıcıda ilgili kodun çalışmasını sağlayabilir. 
  3. DOM Based XSS çeşidinde ise zararlı paylaod sunucuya hiç gitmemekte, doğrudan kullanıcının tarayıcısındaki DOM ortamında çalışmaktadır. 



Bu konuda owasp.org'dan daha detaylı bilgi alınabilir. Ek olarak web uygulama güvenliği testleri ile uğraşan uzmanların da yazdığı oldukça fazla yazı var. Benim bu yazıda değineceğim konu ise XSS'e karşı alınabilecek örnek bir önlemdir.

Asp.Net web forms için yapacağımız örnek bir sayfadan aldığımız girdiyi başka bir sayfada yazdıracağımız çok basit bir örnek olacak. Tasarım, kullanıcıdan bir girdi almak için bir textbox ve bir submit butonu içerecek. Bir tane de Person isimli çok basit class olacak:

    public static class Person
    {
        public static string Name;
    }

Butona basıldığında da şöyle bir kod çalışacak.

    protected void btnSubmit_Click(object sender, EventArgs e)
    {
        Person.Name = txtName.Text;
        Response.Redirect("PageTwo.aspx");
    }

Yapılmak istenen Person'ın Name property'sini diğer sayfada yazdırmak olacağından diğer sayfa page load event'ine de şu kodu yazalım:

    protected void Page_Load(object sender, EventArgs e)
    {
        Response.Write(Person.Name);
    }

Buna ek olarak web.config dosyasında şu ayarı yapalım (Bu konuya aşağıda değiniyor olacağım):

  <system.web>
    <pages validateRequest="false"/>

  </system.web>


Senaryoya göre girdi gireceğimiz yere çalışacak bir script yazıyoruz, Submit butonuna basıyoruz ve bu girdiyi diğer sayfaya taşıyıp o sayfada render ediyoruz ve tam o sırada karşımıza bir reflected XSS çıkıyor:

Sayfa açılır:
Girdi alanına basit bir XSS vektörü yerleştirilir:

Ve işte bir reflected XSS karşımızda:



Böylelikle basit bir reflected XSS örneği yazmış olduk. Burada sorun bir girdi alanından alınan verinin çalıştırılabilir bir script olması ve bizim de bu script'in çalışmasına herhangi bir engel koymamış olmamızdır.


Peki bu durumda biz yazılımcılar ne yapmalı?

Öncelikle web.config'de yaptığımız ayarı açıklayayım. <pages validateRequest="true"/> olsaydı Asp.Net girilen verinin doğrulamasını bizim için yapacaktı ve karşımıza bu girdinin zararlı olduğuna dair şu hatayı çıkaracaktı, yani saldırgan başarılı olamayacaktı:



Fakat bazen projelerimizde true değerini false yapmak zorunda kalabiliyoruz ve bu da tüm sayfalarda validation'ı kapatılmasına ve zararlı bir script yazıldığında kontrol edilmemesine neden olmaktadır. Kapatmak eğer gerekli ise tüm proje yerine web form için her sayfaya ayrı ayrı yani sayfa bazlı da yapılabilir:

<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="PageOne.aspx.cs" Inherits="AntiXSSSampleWithXSS.PageOne" ValidateRequest="false" %>

Aynı ayar gerekli ise Asp.Net MVC için controller'a [ValidateInput(false)] şeklinde yapılabilir, field'lar için de [AllowHtmlattribute'u yazılabilir.

XSS için alınabilecek önlem validation'dur. Bunu yapmak için kendi whitelist veya blacklist'imizi oluşturabilir ve bu listelere göre input encoding ya da output encoding yapılabilir. Hem input encoding hem de output encoding yapılmamalıdır zira bu seçim istenmeyen durumlar ortaya çıkaracaktır. Whitelist veya blacklist oluşturmak da her zaman çok güvenilir bir yöntem olmayabilir. Çünkü kendi oluşturduğumuz mimaride encoding sırasında veya öncesinde veya sonrasında öngörülemeyen ya da işlere engel olabilecek durumlarla karşılaşılabilir.

Microsoft AntiXSS kütüphanesi işte tam bu noktada işimizi kolaylaştırıyor. Önceleri Nuget Package Manager'dan indirip projemize dahil edebiliyorken artık yeni açtığımız projelerde hali hazırda kullanabileceğimiz şekilde geliyor. Kullanacağımız yerde sadece using System.Web.Security.AntiXss;'i eklemek yeterli. Nuget'ten eklemek gerekiyorsa da aşağıdaki gibi aratıp ilk sırada AntiXSS by Microsoft isimli olanı projeye dahil edilebilir:



Örneğimizdeki kod blogunu output encoding yöntemi kullanarak yani şu şekilde değiştirerek kullanılabilir.:

Response.Write(AntiXssEncoder.HtmlEncode(Person.Name, false));

Sayfa render edildiğinde ise saldırgan tarafından input alanından yazılan script, bir script gibi çalıştırılmadan kullanıcıya yansıyacaktır:


Encoding işlemi html tarafında bir output encoding şeklinde yapılacaksa örneğin şu şekilde yapılabilir:

<td><%# Server.HtmlEncode(Eval("NAME").ToString()) %></td>



XSS'si bir başka yazımda MVC ile kurcalamayı düşünüyorum. Bu yazımda XSS'i kısaca anlattıktan sonra klasik Asp.Net örneği üzerinden alabileceğimiz bir savunma yönteminden bahsetmiş oldum. Faydalı olması dileğiyle.



1 yorum: