Smarty<=3.1.32 代码执行漏洞分析—CVE-2017-1000480

先知安全技术社区独家发文,如需转载,请先联系社区授权;未经授权请勿转载。

Smarty简介

Smarty是一个php模板引擎,其项目地址:https://github.com/smarty-php/smarty。

smarty据有模板编译功能。当访问一个模板文件时,smarty会根据模板文件在设置的编译目录中生成对应的php脚本(即编译文件),此后若再次访问该模板文件时,倘若模板文件未更新,则smarty会直接读取第一次生成的php脚本,而不是重新生成另一个。倘若访问另一个模板,则会生成另一个新的php脚本(编译文件)

环境搭建

测试环境:Linux

根据commit信息,我们检出 6768340,此时漏洞还未修复。

index.php:

漏洞分析

参数通过传入,定义在 smarty_internal_templatebase.php 中,它调用了 。

定义在 的 156 行左右,在该方法定义中,也即整个文件的174行左右:

会调用方法,将我们的传入的参数创建成一个模板,

接着会调用render方法,进行模板渲染。

render方法定义在中,第105行开始对前面生成的模板进行处理:

process方法定义在第131行。现在初次访问,也即文件的第138行会对模板文件进行编译,即如简介中所言开始生成编译文件:

方法定义在同文件的第169行,在第181行装载完编译器后(loadCompiler()),调用write方法进行写操作:

跟入方法,定义第334行:

create是生成编译文件代码的方法,定义在第28行,为显示变量情况,这里我加了一句

在第44行,在生成output内容时有如下代码:

将 的内容直接拼接到了里。这段代码是为了生成编译文件中的注释,的头尾有注释符号和。

现在考虑如何利用,我们需要闭合前面的注释符号,即payload的最前面需要加上。同时还要把后面的给注释掉,可以在payload最后加上。中间填上php代码即可。另外需要注意的是,在win平台下,文件名中不允许有,而smarty框架的生成的编译文件的名字会含有我们的payload,所以在win下时会直接提示创建文件失败。

在linux平台下即可利用成功。

漏洞修补

查看commit记录:https://github.com/smarty-php/smarty/commit/614ad1f8b9b00086efc123e49b7bb8efbfa81b61

添加了过滤,将可能闭合的变为:

在另外几处文件中也进行了过滤,要求只能出现字母和数字:

题外话

直接看生成的编译文件,会发现有两个输出点,第二个输出点在单引号内,但这个无法逃逸。在的第47行,使用的是来导出变量内容的值:

而如漏洞修补一节中所言,添加过滤后,引号会被直接去除。

  • 发表于:
  • 原文链接http://kuaibao.qq.com/s/20180124G08P5L00?refer=cp_1026
  • 腾讯「云+社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 yunjia_community@tencent.com 删除。

扫码关注云+社区

领取腾讯云代金券