Solução
Nome | Valor |
---|---|
Vulnerabilidade | Server Side Template Injection (SSTI) |
CWE | CWE-1336 |
OWASP Top Ten | A03_2021-Injection |
Uma vulnerabilidade de SSTI é quando o usuário consegue injetar instruções para um template que será renderizado no lado do servidor. Como muitas engines de templates são bem poderosas, isso pode permitir que o cliente consiga ler dados sensíveis da aplicação/servidor ou até mesmo execute código no servidor. Quando uma vulnerabilidade resulta na execução remota de código não intencional, ela é uma vulnerabilidade de Remote Code Execution (RCE).
No caso desse exercício, o Jinja2 é a engine utilizada e ele permite a execução de código Python dentro das tags de template. Apesar do código ser executado em um ambiente isolado do restante da aplicação, isso não garante a segurança da execução do código.
Para conseguir explorar esse exercício e obter um RCE, a seguinte lógica deve ser seguida:
- Obter acesso a classe de objeto base do Python
(
object
). - Ler a lista de subclasses da classe
object
disponíveis no ambiente. - Procurar por alguma subclasse que possa ser útil para a
execução de código no sistema.
- Alternativamente, é útil procurar por uma classe que permita importar módulos.
- Usar a classe para executar o código ou importar um
módulo que possa ser usado para isso (ex.: o módulo
os
).
Se a função builtin __import__
estiver disponível, tudo se torna mais simples porque basta
usar ela para importar o módulo os
e ser feliz.
Exemplo:
{
"content": "{{ __import__('os').popen('cat /etc/passwd'
).read() }}",
"global_variables": {}
}
Mas infelizmente, provavelmente, não vai ser fácil assim. Então a lógica explicada acima será necessária. Seguindo passo por passo:
- Injetar
{{ ''.__class__ }}
lhe dá acesso a classestr
. - A propriedade
__mro__
de uma classe pode ser usada para ler a classe de onde ela herda.- Portanto uma das classes em
{{ ''.__class__.__mro__ }}
é a classeobject
que precisamos.
- Portanto uma das classes em
- O método
__subclasses__()
de uma classe lista todas as suas subclasses.- Ou seja,
{{ ''.__class__.__mro__[1].__subclasses__() }}
lista todas as subclasses deobject
.
- Ou seja,
- Na lista de subclasses, podemos procurar por uma útil
para o RCE.
- Eu encontrei a
<class 'pkgutil.ImpLoader'>
(em ambiente Python 3.11) que pode ser usada para importar um módulo dinamicamente, ao estilo__import__()
.
- Eu encontrei a
- De resto, basta estudar o código/documentação da classe encontrada para saber como usá-la.
RCE completo:
{
"content": "{{ ''.__class__.__mro__[1].__subclasses__()[362](
'os', None, 'os', ('', '', 7)).load_module('os').popen('cat /et
c/passwd').read() }}",
"global_variables": {}
}
É pouco provável que esse payload funcione no seu ambiente, pois ele será diferente.
Crie um ambiente local para executar esse exercício e explorar um RCE.