Herkese merhaba, bu yazımda sizlere elimden geldiğince Server-Side Template Injection’ın ne olduğunu, bu açığın nasıl sömürülebileceğini ve bu saldırıya maruz kalmamak için ne gibi önlemler almamız gerektiğini anlatmaya çalışacağım.
Vakit kaybetmeden Server-Side Template injection’ın ne olduğu ile başlayalım.
Server-Side Template Injection Nedir?
Kullanıcıdan alınan inputların direkt olarak template engine tarafından render edilmesinden dolayı oluşan bir güvenlik açığıdır. Saldırganlar, bu açığı kullanarak Template Engine tarafından render edilecek olan değere kendi şablonlarını sıkıştırırlar. Saldırganlar tarafından sıkıştırılan bu şablonlar render edildikten sonra saldırganlar, Arbitrary File Read, Remote Command Execution gibi kritik zafiyetler elde edebilirler.
Örneğin;
Aşağıdaki kodu incelediğimizde kullanıcıdan, isim parametresi ile bir değer alındığını ve alınan bu değerin Merhaba ile concatenate edilip render edildiğini görüyoruz.
$output = $twig->render("Merhaba ". $_GET['isim']);
Burada bariz bir SSTI zafiyeti vardır. Bunun sebebi; kullanıcıdan alınan isim parametresindeki değerin doğrudan render fonksiyonuna verilmesidir.
Template Engine’ lerin neden kullanıldığını daha iyi anlayabilmemiz için öncelikle MVC mimarisine göz atalım.
MVC Mimarisi Nedir?
- Model-View-Controller kelimelerinin baş harflerinden oluşur.
- Web uygulamaları geliştirmek için oluşturulmuş bir tasarım modelidir.
- Backend ve Frontend kodlarının ayrı katmanlarda yazılmasını sağlar. Bu sayede spagetti kod yazımının önüne geçilmiş olur.
Model Nedir?
Model, MVC’de projenin iş mantığının (business logic) oluşturulduğu bölümdür. İş mantığıyla beraber doğrulama (validation) ve veri erişim (data access) işlemleri de bu bölümde gerçekleştirilmektedir.
View Nedir?
View, MVC’de projenin arayüzlerinin oluşturulduğu bölümdür. Bu bölümde projenin kullanıcılara sunulacak olan HTML dosyaları yer almaktadır.
Controller Nedir?
Bu bölümde View ile Model arasındaki bağlantı kurulur. Kullanıcılardan gelen istekler (request) Controller’larda değerlendirilir, isteğin detayına göre hangi işlemlerin yapılacağı ve kullanıcıya hangi View’ın döneceği (response) belirtilir.
Template Engine Nedir?
- Web uygulamalarında kullanıcılara dinamik veriler sunmak için kullanılır. Örneğin merhaba Sefa; buradaki Sefa sadece bana özel oluşturulmuştur. Ahmet kullanıcısı için merhaba Ahmet olacaktır.
- Controller katmanından gelen veriyi işleyip HTML formatında kullanıcıya iletir.
- MVC Mimarisinde View katmanında yer almaktadır.
Template Injection’ın Etkileri Neler Olabilir?
NOT: Olabilir dememin sebebi; birbirinden farklı bir sürü template engine vardır. Bu Template Engine’lerden bazıları default olarak sandbox gibi yapılarda geldiğinden dolayı her zaman bu sandboxlardan kaçıp RCE elde etmek mümkün olmayabilir.
- Uzaktan kod çalıştırma,
- Dosya okuma-yazma, LFI/RFI, bilgi ifşası ve yetki yükseltme zafiyetleri.
Template Engine Türleri Nelerdir?
- PHP’de Twig ve Smarty
- Java’da Freemaker, Velocity ve WebMacros
- Python’da Django, Jinja2 ve Mako
- Javascript’te Rage, Jade ve Mustache
Template Engine’ler yukarıda saydıklarımla sınırlı değillerdir. Daha bir sürü farklı Template Engine çeşidi vardır. Bu kadar fazla Template engine’nin olması gözünüzü korkutmasın çünkü çoğu Template Engine’in söz dizimi birbirine benzerdir.
Server-Side Template Injection zafiyetinin sömürülmesi birkaç adımdan oluşur. Bunlar;
- İlk olarak SSTI zafiyeti bulunan parametreyi tespit edilir.
- Ardından Portswigger’ın bizlere sağladığı karar verme ağacı sayesinde backend’de hangi Template Engine’inin kullanıldığı saptanır.
- Template Engine’in içerisinde gelen methodlardan, objelerden ya da custom olarak oluşturulmuş objelerden yararlanarak RCE elde edilir.
Senaryo #1
İlk olarak hangi parametrenin SSTI zafiyetine karşı savunmasız olduğunu buluyoruz.
Sefa yazıp arattığımızda Sefa’nın tekrar ekrana basıldığını görüyoruz. Farkettiyseniz Merhabadan sonra gelen string dinamik olarak oluşturuluyor. Burada Template Engine kullanılma ihtimali vardır.
Yazdığım string’in tekrar ekrana basıldığını görünce parmaklarım istemsizce XSS payload’ı yazdı. :)
REKLAM: XSS ile ilgili daha detaylı bilgi edinmek isterseniz daha önceden yazmış olduğum yazıma buradan ulaşabilirsiniz.
Sayfanın kaynak kodunu incelediğimizde'"><
karakterlerinin encode edilmediğini görüyoruz.
HTML context’ de olduğumuz için < >
karakterleri encode edilmeliydi.
Basit bir XSS payload’ı yazıp submit butonuna basıyoruz.
Submit butonuna basar basmaz bir pop-up bizleri karşılıyor.
Bir çok template engine’in söz dizimi dikkate alınarak hazırlanmış polyglot payload $({{<%[%'"}}%\
adı verilen payloadı yazıp submit butonuna basıyoruz. Eğer şanslıysanız, dönen hata mesajında hangi Template Engine’in kullanıldığını belirten bir bilgi olur.
Biz o kadar şanslı olmadığımız için dönen hata mesajında hangi Temeplate Engine’inin kullanıldığını gösteren bir bilgi yok. Bu gibi durumlarda hangi Template Engine’inin kullanıldığını tespit etmek için Port Swigger’ın bizlere sunduğu karar verme ağacını kullanıyoruz.
Bu ağacın çalışma mantığı; en soldaki payloaddan ${7*7}
başlayarak sırasıyla payloadları göndermeye başlıyoruz. Eğer yazdığımız bu Template’teki ${7*7}
matematiksel işlem gerçekleşirse yani sonuç 49 dönerse yeşil okun olduğu yöne gerçekleşmezse kırmızı okun olduğu yöne doğru ilerliyoruz.
Okurlarımın arasında renk körü olma ihtimalini varsayarak;
- Aşağı yönlü olan oklar kırmızı,
- Yukarı ve düz yönlü olan oklar yeşil renktedir.
İlk olarak ${7*7}
yazarak başlıyorum. Eğer sonuç 49 dönerse yani Template Engine’e kendi yazdığımız matematiksel işlemi hesaplattırabilirsek ağaçta yukarı doğru hareket edeceğiz. Aksi taktirde aşağı doğru hareket edeceğiz.
Yukarıdaki resimde de gördüğümüz gibi yazdığımız ${7*7}
işlemimiz gerçekleşmedi. Inputumuzu {{7*7}}
olarak değiştirip tekrar submit butonuna basıyoruz.
Bu sefer bir önceki paylod’ dan farklı olarak 49 sonucunun ekrana basıldığını görüyoruz. Bu payload’ımız çalıştığı için yeşil renkli oku takip edip {{7*'7'}}
payload’ını yazıp sumbit butonuna basıyoruz.
Gördüğünüz gibi bu payload’ımızın sonucunu da 49 olarak ekrana basıldı. Bu da demek oluyor ki backend’de Twig Template Engine’i kullanılıyor.
İnternette Twig Template Engine’ini kullanarak nasıl RCE elde edebiliriz diye arattığımda bu Github reposu ile karşılaştım. Burada, bütün Template Engine’ lere ait payloadlar bulunuyor.
Yukarıdaki 3. payload’ı girdiğimizde sistemde gerçekten de komut çalıştırabildiğimizi görüyoruz.
Zafiyetin oluşmasına sebep olan kod aşağıdaki gibidir.
Bu kodda ufak bir değişiklik yapıyoruz. Bu değişiklik bizim için küçük ama Web Uygulaması için çok büyük bir değişikliktir. :)
Önceden hatırlarsınız {{7*7}}
payload’ını gönderdiğimizde 49 sonucunun bastırıldığını görmüştük. Render fonksiyonuna verilen veri üzerinde yaptığımız ufak bir değişikliğin ardından tekrardan {{7*7}}
payload’ını gönderiyoruz.
Yukarıdaki resimde de gördüğümüz gibi yazdığımız matematiksel işlem hesaplanmadı. Bu da demek oluyor ki sistemimiz artık SSTI saldırısına karşı zafiyetli değil.
Kodda yapılan değişikliğin ardından uzaktan komut çalıştırmanın da mümkün olmadığını göstermek için aşağıdaki payload’ı tekrardan gönderiyoruz.
Gördüğünüz gibi whoami komutu da çalışmadı.
Template Injection Zafiyetinin Oluşmasını Nasıl Engelleyebiliriz?
Template injection zafiyetinin oluşma sebebinin kullanıcıdan alınan inputların direkt olarak Template Engine tarafından render edilmesinden dolayı olduğunu söylemiştik.
Örneğin;
$output = $twig->render("Merhaba ". $_GET['isim']);
O halde bu saldırıya maruz kalmamak için kullanıcıdan aldığımız inputları direkt olarak render etmek yerine önceden hazırladığımız HTML şablonunu render edip kullanıcıdan aldığımız inputları da bu şablona aktarmamız gerekiyor.
Örneğin;
$output = $twig -> render ("{{name}}",array("name" => $name));
Bu sayede kullanıcıdan aldığımız inputlar HTML şablonuna kodun bir parçası olarak girmeyip data olarak girecektir. Böylelikle de SSTI zafiyetinin oluşması engellenmiş olur.