File size: 2,173 Bytes
046723b
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
#!/usr/bin/env python3

# run from dir above changedetectionio/ dir
# python3 -m unittest changedetectionio.tests.unit.test_jinja2_security

import unittest
from changedetectionio import safe_jinja


# mostly
class TestJinja2SSTI(unittest.TestCase):

    def test_exception(self):
        import jinja2

        # Where sandbox should kick in
        attempt_list = [
            "My name is {{ self.__init__.__globals__.__builtins__.__import__('os').system('id') }}",
            "{{ self._TemplateReference__context.cycler.__init__.__globals__.os }}",
            "{{ self.__init__.__globals__.__builtins__.__import__('os').popen('id').read() }}",
            "{{cycler.__init__.__globals__.os.popen('id').read()}}",
            "{{joiner.__init__.__globals__.os.popen('id').read()}}",
            "{{namespace.__init__.__globals__.os.popen('id').read()}}",
            "{{ ''.__class__.__mro__[2].__subclasses__()[40]('/tmp/hello.txt', 'w').write('Hello here !') }}",
            "My name is {{ self.__init__.__globals__ }}",
            "{{ dict.__base__.__subclasses__() }}"
        ]
        for attempt in attempt_list:
            with self.assertRaises(jinja2.exceptions.SecurityError):
                safe_jinja.render(attempt)

    def test_exception_debug_calls(self):
        import jinja2
        # Where sandbox should kick in - configs and debug calls
        attempt_list = [
            "{% debug %}",
        ]
        for attempt in attempt_list:
            # Usually should be something like 'Encountered unknown tag 'debug'.'
            with self.assertRaises(jinja2.exceptions.TemplateSyntaxError):
                safe_jinja.render(attempt)

    # https://book.hacktricks.xyz/pentesting-web/ssti-server-side-template-injection/jinja2-ssti#accessing-global-objects
    def test_exception_empty_calls(self):
        import jinja2
        attempt_list = [
            "{{config}}",
            "{{ debug }}"
            "{{[].__class__}}",
        ]
        for attempt in attempt_list:
            self.assertEqual(len(safe_jinja.render(attempt)), 0, f"string test '{attempt}' is correctly empty")



if __name__ == '__main__':
    unittest.main()