-
-
Notifications
You must be signed in to change notification settings - Fork 912
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request from GHSA-4r7v-whpg-8rx3
* CVE-2024-32651 - Security fix - Server Side Template Injection in Jinja2 allows Remote Command Execution * use ImmutableSandboxedEnvironment also in validation
- Loading branch information
Showing
15 changed files
with
147 additions
and
44 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
""" | ||
Safe Jinja2 render with max payload sizes | ||
See https://jinja.palletsprojects.com/en/3.1.x/sandbox/#security-considerations | ||
""" | ||
|
||
import jinja2.sandbox | ||
import typing as t | ||
import os | ||
|
||
JINJA2_MAX_RETURN_PAYLOAD_SIZE = 1024 * int(os.getenv("JINJA2_MAX_RETURN_PAYLOAD_SIZE_KB", 1024 * 10)) | ||
|
||
|
||
def render(template_str, **args: t.Any) -> str: | ||
jinja2_env = jinja2.sandbox.ImmutableSandboxedEnvironment(extensions=['jinja2_time.TimeExtension']) | ||
output = jinja2_env.from_string(template_str).render(args) | ||
return output[:JINJA2_MAX_RETURN_PAYLOAD_SIZE] | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
#!/usr/bin/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() |
Oops, something went wrong.