-
-
Notifications
You must be signed in to change notification settings - Fork 101
Twig template injection #401
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
base: develop
Are you sure you want to change the base?
Changes from 3 commits
3dcf658
3fe44eb
f01c7f5
70bcff2
1bafbf6
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,77 @@ | ||
| import asyncio | ||
| import logging | ||
|
|
||
| from tanner.config import TannerConfig | ||
| from tanner.utils.php_sandbox_helper import PHPSandboxHelper | ||
| from tanner.utils import patterns | ||
|
|
||
|
|
||
| class TwigTemplateInjection: | ||
| def __init__(self, loop=None): | ||
| self._loop = loop if loop is not None else asyncio.get_event_loop() | ||
| self.logger = logging.getLogger("tanner.twig_template_injection") | ||
| self.helper = PHPSandboxHelper(self._loop) | ||
| self.autoloader = TannerConfig.get("TWIG_PATH", "autoloader") | ||
| self.stringloader = TannerConfig.get("TWIG_PATH", "stringloader") | ||
|
|
||
| async def get_injection_result(self, code): | ||
| """ | ||
| Injects the code from attacker to vulnerable code and get emulation results from php sandbox. | ||
| :param code (str): Input payload from attacker | ||
| :return: twig_injection_result (dict): file_md5 (md5 hash), stdout (injection result) as keys. | ||
| """ | ||
|
|
||
| vul_code = """ | ||
| <?php | ||
|
|
||
| require '%s'; | ||
| require '%s'; | ||
|
|
||
| Twig_Autoloader::register(); | ||
| $loader = new Twig_Loader_String(); | ||
| $twig = new Twig_Environment($loader); | ||
| $twig->addExtension(new \\Twig\\Extension\\StringLoaderExtension()); | ||
| $payload = "%s"; | ||
| $result = $twig->render($payload); | ||
| echo $result; | ||
| ?> | ||
| """ % ( | ||
| self.autoloader, | ||
| self.stringloader, | ||
| code, | ||
| ) | ||
|
|
||
| self.logger.debug( | ||
| "Getting the twig injection results of %s from php sandbox", code | ||
| ) | ||
| twig_injection_result = await self.helper.get_result(vul_code) | ||
|
|
||
| return twig_injection_result | ||
|
|
||
| def scan(self, value): | ||
| """ | ||
| Scans the input payload to detect attack using regex | ||
| :param value (str): code from attacker | ||
| :return: detection (dict): name (attack name), order (attack order) as keys | ||
| """ | ||
|
|
||
| detection = None | ||
| if patterns.TEMPLATE_INJECTION_TORNADO.match(value): | ||
|
rjt-gupta marked this conversation as resolved.
|
||
| detection = dict(name="twig_template_injection", order=3) | ||
|
rjt-gupta marked this conversation as resolved.
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I tested with super simple string /foobar?b={{3*%272%27}} There are 2 possible detections: Since Any ideas how to distinguish? @mzfr @rjt-gupta
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. For twig this case should give
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. we need something that distinguishes these two..
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. yeah the regex is almost similar so it' hard to distinguish. Also afeena can you please tell me how did you tested it? I mean the setup I want to know what I am doing wrong.
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @mzfr scan works perfectly fine, if you print possible detection you can see it. the only problem in the signature of the |
||
| return detection | ||
|
|
||
| async def handle(self, attack_params): | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
the signature of the function is wrong. base emulator calls every handle with session that is why function was not called properly, works for me now |
||
| """ | ||
| Handler of emulator | ||
| :param attack_params (list): contains dicts as elements with id and value (payload from attacker) as keys | ||
| :return: (dict): value (result of emulator), page (if set to true the payload will be injected to index.html | ||
| itself) as keys. | ||
| """ | ||
|
|
||
| result = await self.get_injection_result(attack_params[0]["value"]) | ||
| if not result or "stdout" not in result: | ||
| self.logger.exception( | ||
| "Error while getting the injection results from php sandbox.." | ||
| ) | ||
| return dict(status_code=504) | ||
| return dict(value=result["stdout"], page=False) | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You need to add emulator here in order to enable it
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
POST too.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
tanner/tanner/emulators/base.py
Line 114 in 40e2357
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
oh okay