考点

  • 判断SSTI类型
  • 分析过滤
  • 构造payload

flask + jinja2 的 SSTI ---[攻防世界shrine] - 图1

解题

打开页面就是一段源码

flask + jinja2 的 SSTI ---[攻防世界shrine] - 图2

这明显是个flask在/shrine/下的SSTI

而且对payload进行了过滤了

  1. - 对小括号进行了替换,将(和)替换为空字符串![](https://cdn.nlark.com/yuque/0/2020/png/573149/1586061938569-eadb42d9-94aa-4236-8970-51ff36b394a0.png)
  2. - configself添加进了黑名单![](https://cdn.nlark.com/yuque/0/2020/png/573149/1586061963539-04f81aec-6996-4e2b-8e0b-b93b105fd800.png)
  • 既然是模板注入,那么我们先试试{{7*7}}

flask + jinja2 的 SSTI ---[攻防世界shrine] - 图3

  • 再试试{{7*’7’}}

flask + jinja2 的 SSTI ---[攻防世界shrine] - 图4

经过这两个测试发现是jinjia2或者Twig,后端源码是为flask

所以这个是关于flask+jinjia2的SSTI

至于为什么 请看图

flask + jinja2 的 SSTI ---[攻防世界shrine] - 图5

  • {{‘’.class.mro[2].subclasses()}}

flask + jinja2 的 SSTI ---[攻防世界shrine] - 图6

这里明显对()进行了过滤

这能从别的地方入手,例如flask的内置函数和变量

当然,config和self也被加入了黑名单

但是通过变量去读取app.config也会涉及到()的使用

所以值剩下内置函数

  • get_flashed_messages(), url_for()

构造payload

  • {{getflashedmessages.__globals[‘current_app’].config[‘FLAG’]}}