什么是模板:
模板引擎用于使用动态数据呈现内容。此上下文数据通常由用户控制并由
模板进行格式化,以生成网页、电子邮件等。模板引擎通过使用代码构造
(如条件语句、循环等)处理上下文数据,允许在模板中使用强大的语言
表达式,以呈现动态内容。如果攻击者能够控制要呈现的模板,则他们将
能够注入可暴露上下文数据,甚至在服务器上运行任意命令的表达式。
flask:
Flask是一个使用 Python 编写的轻量级 Web 应用框架。模板引擎则使用 Jinja2,学习python模板注入就要先弄清flask的工作流程。Flask的基本模式为在程序里将一个视图函数分配给一个URL,每当用户访问这个URL时,系统就会执行给该URL分配好的视图函数,获取函数的返回值并将其显示到浏览器上。
模板引擎(这里特指用于Web开发的模板引擎):
简单来说是为了使 用户界面(html文件)与业务数据(视图函数)分离而产生的,它可以使得代码的可读性增强并容易理解与维护.
类(基类子类):
Python3把所有的功能、函数等都封装在类里面 如str类下封装着与字符串相关的功能 如split()等 list类封装着与列表相关的功能 如append()等而这些类全都继承一个基类:object类 而我们之前说的那些模块 就属于object的子类,继承的作用就是子类继承了一个父类 就可以使用父类的一些方法。
如何利用模板注入这一个漏洞:
python中,我们最终的目的是为了绕过python终端 进入服务端的系统 然后使用系统命令达到我们的目的(找flag)所以 在python中 你也得知道一些基本姿势 其实就是通过python语言来对系统进行操作
os.popen()方法用于从一个命令打开一个管道
(popen()返回的是一个文件对象 里面放着执行命令后返回的内容
通过.read()方式读出)这就是一个简单的绕过python终端 使用系统
命令的例子
利用:
我们要解决的是如何利用ssti漏洞达os.popen(‘catflag’).read()的目的直接在{{}}里加import os再os.popen(‘catflag’).read()是不可以的,其实我们并不是只能通过 ‘import os‘ 才能使用os库的相关函数 一些模块里存在和‘import os‘这个表达式作用相同的函数,同样可以引用os库从而使用os库的函数 而这些模块存在于python内部文件中我们只需要找到这些模块所在位置 然后通过这些模块来使用函数也可以达到绕过终端 执行系统命令的目的,我们需要使用一些特殊的方法。
模板注入题目的思路:
jinja2模板中的表达语句{{…}}模板注入,{{…}}中的会当做命令执行,我们需要采用自带的模块和基类调用我们需要的函数,输入参数等。绕过的时候注意是python2还是python3 不同形式的python3中可能不存在一些库
如:
python两对{}包裹的会被当做命令执行,我们可以来读取文件等可以简单的用于测试是否存在模板注入 {{9-3}}会返回6, 则可执行在Jinja2模板引擎中。
{{}}是变量包裹标识符。{{}}并不仅仅可以传递变量,还可以执行一些简单的表达式注意 对象要使用jinjia2的{{}}能使用的对象 就是python的数据类型 如字符串 列表等。
1.class
返回一个实例所属的类
mro 返回当前对象的所有父类
或base 返回当前对象的父类
base和mro都是用来寻找基类的
3.subclasses()
是一个内置方法,获取一个类所有的子类,返回值是一个列表
4.init 类的初始化方法
5.globals 对包含函数全局变量的字典的引用
6.利用{{ config.items() }}可以查看服务器的配置信息
获取基类的几种方法:
[].class.base”.class.mro[2]
().class.base
{}.class.base
request.class.mro[8] 或者 [].class.bases[0]
之后我们开始寻找我们可用的子类ssti的主要目的就是从这么多的子类中找出可以利用的类(一般是指读写文件的类)加以利用。
如:我们可以利用的方法有等 (file是的40号)。
().class.base.subclasses()40.read()
//用file的方式读取了etc/passwd里的信息
寻找可用的子类(脚本遍历):
读写文件:
可以直接调用system函数
().class.base.subclasses([71].init.globals[‘os’].system(‘ls’)
或者
().class.base.subclasses([71].init.globals[‘os’].listdir(‘.’) //读取本级目录
一道题目(攻防世界Web_python_template_injection):
可以看到目录列表
运用file()40号就读取到了fl4g的内容。