《Remote Code Execution from SSTI in the Sandbox Automatically Detecting and Exploiting Template Escape Bugs》论文笔记

文章发布时间:

最后更新时间:

Remote Code Execution from SSTI in the Sandbox:Automatically Detecting and Exploiting Template Escape Bugs

  • 前置

    • 模板引擎

      适用于前后端不分离的架构,后端接收请求数据后,将数据通过 模板引擎 解析渲染成视图后再返回给前端,由前端展示。可以简单理解为访问一个URL后直接得到html页面

      模板引擎的作用就是实现逻辑与数据的分离,最终可将模板文件和数据通过模板引擎的渲染生成最终的HTML代码

      Untitled

    • SSTI 漏洞成因

      服务端接收了攻击者的恶意输入以后,未经任何处理就将其作为 Web 应用模板内容的一部分,模板引擎 在进行目标编译渲染的过程中(一般可以执行各种表达式),执行了攻击者插入的可以破坏模板结构的语句(恶意Payload),因而可能导致了敏感信息泄露、代码执行、GetShell等问题

    • 如何挖掘和判定?

      利用模板表达式常用的特殊字符来尝试 fuzz 模板

      怎么判断是哪种模板引擎?

      • 报错信息
      • 根据执行结果(依赖于不同模板语言特性)

        Untitled

    • 模板逃逸漏洞

      主要发生在基于设计的渲染引擎渲染过程中,由于模板代码的内容可控,可以在生成PHP代码的过程中逃离原本的语义,注入PHP代码造成 RCE

      Untitled

  • Abstract

    模板引擎在 web 应用中可以简化用户接口的开发,它所提供的强大能力可以被攻击者利用 SSTI 注入发起服务端的攻击,包括 RCE,因此现代模板引擎通常会提供沙箱机制作防御。

    作者从一个模板引擎被忽视的沙箱绕过漏洞入手(模板逃逸),研究并解决了其利用手法对于模板引擎语法和渲染逻辑的依赖问题,结合最新技术开发出 TEFuzz 自动化检测利用工具,可应用于 PHP 的7款模板引擎上。

  • 研究动机

    从一个 CVE 入手

    公开的关于模板逃逸的漏洞很少,然而模板转换过程涵盖了模板代码解析和PHP代码生成两个部分,这涉及到大量复杂的字符串操作,因此模板逃逸漏洞在现实中不应该是罕见的,值得研究

  • Introduction

    • 模板逃逸漏洞概述

      大部分模板引擎在渲染过程中采用基于生成的设计方案,即会在渲染过程中将模板文件转换成 PHP 文件,并执行。同时,通过缓存生成的 PHP 文件,渲染过程可以达到近乎原始PHP代码的执行性能。

      由于模板引擎一些不恰当的实现,模板代码在渲染过程中可以逃离模板的语义导致注入PHP代码到生成的PHP文件当中。

      威胁模型

      敌手的能力:

      1. 直接形式的模板注入
      2. 利用其它类型的漏洞如文件上传,造成模板文件被修改控制
      3. 滥用 Web 应用的正常功能(如模板文件编辑功能)
    • 研究目标:开发一款自动化的工具来检测模板逃逸漏洞并检测它们的可利用性

      面临的挑战:

      1. 漏洞的根源——模板渲染逻辑,与语法分析紧密关联,难以理解和自动化推断
      2. 输入 POC 很难构造,EXP 更难构造。需要调整 payload 以适应 PHP 文件中转义点(EP)的语义环境(EC)
      3. 模板逃逸漏洞是基于语义层面的 bug ,很难去识别
    • 提出:针对模板逃逸漏洞设计的模糊测试框架 TEFuzz

      动态测试结合了 Fuzz 的优势,避免了对于复杂模板语法的理解,并且利用了生成的 PHP 代码来方便检测漏洞和利用

      技术问题转变到Fuzz的技术问题上:如何平衡探索和利用,即如何保证测试的代码覆盖率同时减少冗余的测试样例。

      Untitled

![Untitled](Remote%20Code%20Execution%20from%20SSTI%20in%20the%20Sandbox%20Aut%207020c30e8f32462281b933608ffc7d25/Untitled%204.png)
  • 解决方案设计

    • 针对如何检测模板逃逸 bugs

      Fuzz 原则1:平衡探索和利用。探索阶段:识别更多的 interesting testcases;利用阶段:将 interesing testcases 转换为 PoC

      阶段1:基于探测的 Interesting Testcase 识别

      magic string 插入,推断哪一部分被带入到了 PHP 代码中

      阶段2:PHP语法引导的PoC生成

      观察:payload 触发模板漏洞通常伴随着打破了原生成的 PHP 代码的结构

      利用:包含一些 PHP 语法字符来打破代码结构(判断依据)

      Fuzz 原则2:提高代码覆盖率同时避免冗余测试

      技术1:利用错误反馈自适应调整测试用例

      观察:错误反馈信息通常会传达如何修复引起错误的测试样例;错误反馈信息种类较少

      利用:半自动化的测试用例适配技术

      技术2:利用运行时信息聚合测试用例

      现有的 fuzz 框架的度量(代码覆盖 、调用栈信息) + 拓展

    • 针对如何利用模板逃逸 bugs

      挑战:PoC 可能会在不同的上下文(EC)中破坏PHP代码结构,并且每个破坏的PHP代码结构都必须以其特定的方式修复

      解决:上下文敏感的漏洞利用

      1. 识别出 PHP 代码中 PoC 的转义上下文 EC
      2. 调整 PoC 来保证注入的 PHP 代码符合对应的转义上下文

        贡献:总结了模板逃逸 bugs 的转义语义以及 payload 调整方法

    • 实现细节

      Untitled

      1. 阶段一:Seed Collection

        为每个模板引擎初始化测试样例。

      2. Interesting Testcase Identification

        探测技术创建测试样例 + 错误反馈调整;聚合类似的 interested testcases

        Untitled

        聚合的困难:聚合方法不应该依赖于模板语法的先验知识

        提出语法无关的测试用例聚合技术,判断点1 相似的 interesting testcases 应该拥有相同的代码占用空间 ⇒ 代码覆盖率相同;判断点2 相同的 EP 点 ⇒ magic string 出现在 PHP 文件中的行号一样

      3. PoC 生成

        语法制导测试样例突变技术 + 错误反馈调整 + PoC 聚合

        Untitled

        PoC 聚合:覆盖相似性评估 覆盖行号的 Jaccard index;EP相似性 包含 EP 点的 PHP 代码行之间的 edit distance

      4. How to fix the TE Error?

        人工收集错误信息并编写对应的修正规则:

        • File Adaption 创建对应文件并赋予可读权限
        • Grammar Adaption missing params or attrs; unclosed symbols; unclosed tags
        • Attribute Adaption 改变属性类型
      5. EXP 合成

        识别生成 PHP 文件的转义上下文,调整 PoC 使其包含在 EC 中(闭合语句)

        • 如何识别转义上下文 EC

          分类五种 EC:

          Untitled

          在 AST 层面判断,Poc 本身会破坏 AST 结构难以定位 EP 点;用良性输入替换生成 PHP 文件的 AST ,对比识别出 EP 点及其归属的 EC

          EXP 失效问题根源:忽略掉了模板代码解析过程????

        • 如何正确闭合 PoC 在不同的 EC 中

          1. 利用 EC 和 EP 来寻找对应的闭合 payload (闭合了 EP 之前的语句)
          2. 闭合EP 之后的语句:单行注释符;同样依据 EC 和 EP 去寻找 payload
          3. 在闭合语句中间插入 RCE 代码
  • 实验评测

    • TE 数据集

      拥有沙箱机制/不支持直接执行PHP代码;基于生成PHP式的模板渲染引擎;知名度

      Untitled

      编写 TE 驱动;抽离每个TE的分界符;编写自适应规则

    • 种子收集

      爬虫爬取文档中源代码相关的模板样例,正则编写抽取模板代码

    • 性能评估

      1. 模板逃逸漏洞的普遍性和严重性

        Untitled

        从 PoC 中可以总结出漏洞的成因:

        1. 模板代码解析过程中验证不严
        2. PHP代码生成过程中过滤不严

          并总结了容易产生漏洞的模板引擎特征:

        3. 复杂的模板语法

        4. 模板变量直接映射为PHP变量
        5. “乐观”的模板代码解析原则
        6. 生成PHP代码过程缺少过滤
      2. 对比试验

        与一款 SSTI 扫描器:tplmap 进行对比

        Untitled

        角度1:tplmap 能否发现模板逃逸漏洞?

        角度2:TEFuzz能否指导 tplmap 进行 RCE ?

      3. 真实世界 Web 应用的漏洞挖掘能力

        1. 针对已知漏洞

          分析现存 CVE 中的 SSTI 漏洞的成因,评估其是否符合本文所构建的威胁模型,验证可行性;

          针对实验中涉及到的存在漏洞的模板引擎,利用TEFuzz进行RCE利用探索。通过成功对 CMS 造成 RCE ,来证实模板逃逸漏洞的严重性

        2. 针对 0day 漏洞

          对比试验

          Untitled

          SSTI 扫描器 0 产出 ⇒

          检测依赖于 HTTP 相应,无法识别二次注入;固定的 payload 字典无法自适应不同的注入点上下文语义环境

          手动找 SSTI 注入(根据威胁模型)+ TEFuzz RCE

          Untitled

        3. TEFuzz 设计的性能评估

          测试基于种子和 interesting case 样例生成的有效性、聚合的能力以及错误修复能力

          Untitled

          评估测试样例自适应模块带来的有效性

          Untitled

          针对 EXP 合成模块的探究:

          exp失效的原因:

        4. 模板解析错误。过度闭合转义点上下文语义,导致模板解析过程已经无法通过

        5. 模板验证错误。标签解析后元素格式不符规定

          寻求模板解析验证和 EXP 合成之间的平衡(调整使其通过模板解析验证功能,不可避免地需要去知道模板语法是什么??)

          一些思考:在中间语言层面去挖掘通用型。如果想即符合语法规范,又要能闭合逃逸点上下文,则需要更加复杂的构造(论文中提到高超的 hacking skills),不可避免得在模板的语法作研究,但是本文是绕过它的

  • 限制

    1. 对于新的模板引擎,需要手动抽离分界符、编写驱动和测试样例适应规则,耗费人力
    2. 无法检测种子语料库中未覆盖到的模板标签相关的漏洞
    3. 未考虑到模板引擎当中的控制流/数据流限制
  • 一些思考
    1. 种子语料库的覆盖问题。结合 DL 生成一些模板预料
    2. EXP 合成模块的结果无法通过模板解析过程问题。
  • 参考链接

    [1] https://www.usenix.org/conference/usenixsecurity23/presentation/zhaoyudi

    [2] CVE-2021-26119 PHP Smarty

    [3] https://blog.gm7.org/个人知识库/01.渗透测试/02.WEB漏洞/05.SSTI注入/

    [4] https://smarty-php.github.io/smarty/4.x/

    [5] https://www.anquanke.com/post/id/272393#h2-0