SSTI(Server-Side Template Injection)服务器端模板注入,参考链接

https://portswigger.net/blog/server-side-template-injection这篇文章给出了详细的针对不同模板引擎的攻击方式

https://www.cnblogs.com/tyomcat/p/5440488.html这篇博客给出了Flask/Jinja2攻击方式的详解

SSTI的成因

服务端接收了用户的输入,将其作为 Web 应用模板内容的一部分,在进行目标编译渲染的过程中,执行了用户插入的恶意内容,因而可能导致了敏感信息泄露、代码执行、GetShell 等问题 。在Twig模板引擎中

$twig = new Twig_Environment(new Twig_Loader_String());
$output = $twig->render("Hello {$_GET['name']}"); //若传入name=
echo $output;//output:"Hello 70"

此时服务端将用户的输入作为了模板的一部分,那么在页面渲染时也必定会将用户输入的内容进行模版编译和解析最后输出,Twig模板引擎就会输出中的表达式的值。利用这点,用户便可以 传入恶意代码。

模板引擎的判断

img

注入

这里主要结合QCTF的一道题来整理一下关于jinja2的注入。

img

从404页面发现要读取到flag文件,猜测是SSTI,按照上面给出的判断方式进行测试,(输入,如果返回7777777是Jinja2引擎,如果是49则是Twig引擎),判断出本题是jinja2引擎。接下来便是进行注入。

先插一些注入姿势,这里涉及到比较关键的几个内省对象和组件。

  1. request对象。request对象是Flask的模板全局变量,是当前请求对象,利用这个对象,我们可以在请求中传入一些被ban掉的函数,然后再通过这个对象在请求中获取,从而绕过过滤。
  2. config对象。它是一个类似于字典的对象,其中包含了应用程序所有的配置值 ,例如 可以查看配置
  3. __mro__ 中的MRO代表方法解析顺序,并且定义为,“是一个包含类的元组,而其中的类就是在方法解析的过程中在寻找父类时需要考虑的类,__mro__属性以包含类的元组来显示对象的继承关系,它的父类,父类的父类,一直向上到object 。在注入的时候可以利用这个组件返回当前类的所有父类,我们便可以通过选择返回组元中的元素来访问任一父类。
  4. __subclasses__属性则在这里被定义为一个方法,“每个新式类保留对其直接子类的一个弱引用列表。此方法返回那些引用还存在的子类 ,在注入的时候可以利用这个访问子类

知道了之后之后便可以构造payload ,在这题中,发现class,mro,subclasses都被过滤了,于是考虑利用request绕过,最终的payload: 并在cookie处传入a=__class__; b=__mro__; c=__subclasses__; d=read