分享好友 最新动态首页 最新动态分类 切换频道
2. SSTI(模板注入)漏洞(cms实例篇)
2024-12-26 21:27

上篇《SSTI(模板注入)漏洞(入门篇)》主要介绍了PHP/Python/Java常见的几种模板注入,本篇主要通过cms实例来更好的理解并且挖掘SSTI。

以下cms的源码地址:https://github.com/bmjoker/Code-audit/

先给出漏洞payload:

通过搜索代码执行常用的字段(eval,assert...),定位到此处

查看 maccms_php_v8.xinccommon emplate.php 文件,判断变量是否可控:

可以看到如果想构造代码执行,需要控制变量 $strif ,通读上下文发现一条数据链:

最原本的传进来的数据是 $this->H ,经过 preg_match_all() 函数进行正则匹配,把匹配到的结果赋值给 $iar 这个二维数组,进入for循环遍历数组,将 $iar[2][$m] 所指的元素传入 asp2phpif() 方法进行安全过滤,最后的返回值就是 $strif 。 

这里看到 asp2phpif() 方法仅是对一些字符的替换。

先来追踪一下 ifex() 函数在哪里被调用:

最后定位到了 maccms_php_v8.xindex.php 文件,发现了调用的地方 $tpl->ifex(),那么 $this->H 参数从哪里传进来呢?

最上面看到了这样一段代码:$m = be('get','m'),跟进 be() 这个方法:

再结合网站的请求:

大概了解了网站接收参数的方法。 $m = be('get','m'):就是通过get请求获取m的参数。然后获取到的参数被 explode() 方法以 - 分割成数组传递给 $par,取数组的第一个元素赋值给$ac,判断 $ac 所指的元素是否在 $acs 的数组中,如果存在的话就使用 include 包含 /inc/module/ 目录下以 $ac 所指元素命名的php文件。

根据payload,进入vod.php文件,这里给出关键代码:

当我们调用 search 方法时,就会进入此分支,通过 be("all","wd") 获取用户传进来的wd的参数,传入 chkSql 方法,然后赋值给 $tpl->P["wd"]

仅是使用 htmlEncode() 方法对一些字符判空,转义。

$tpl->H 就是传入ifex() 方法中的 $this->H 参数,因为 $tpl = new AppTpl()。上图代码中 $tpl->H 加载文件 vod_search.html 然后展示给前端。

$colarr$valarr两个参数数组,经过 str_replace() 方法,将 vod_seach.html 中的类似 {page:des} 的字段替换成 $tpl 所指向的字段,漏洞导致的关键是这个 $tpl->P["wd"] 是我们前端可控的参数。

执行完上面的赋值,回到index.php中下一步就调用 ifex() 方法

$tpl->H 就是替换过后的 vod_search.html 文件

这样的话再倒过来看最初的 template.php 文件,是不是就清楚多了

通过for循环一次一次的匹配到类似  {if-A:"{page:typepid}"="0"}  的字段,赋值给变量 $strif,传入eval方法导致代码执行漏洞 

下面就是如何构造合适的payload绕过正则表达式:{if-([sS]*?):([sS]+?)}([sS]*?){endif-1}

 类似这样即可:

真正代码调试过的人,可能有的人会有疑问,因为使用上面payload的话  if (strpos(",".$strThen,$labelRule2)>0),if (strpos(",".$strThen,$labelRule3)>0) 两个循环都无法进入,所以真正的漏洞出发点在 else:

漏洞演示效果:

静态插桩打印 $iar 的值:

打印 $strif 的值:

参照上面打印 $iar 的值,第三个 phpinfo() 进入else分支的eval函数中,导致代码执行。

ofcms是由JFinal开发的内容管理系统。

从pom.xml可以看到引入freemarker-2.3.21依赖

JFinal允许多模板共存,如果想要使用freemarker模板,需要在configConstant配置

然后再使用 JFinal.me() 调用模板,使用 put 用来替换原来输出response html代码输出到浏览器

到这里我们是不是可以理解为网站的html文件由FreeMarker模板进行渲染。

ofcms后台模板文件

任意选择一个html文件,再文件中插入我们的payload:

保存,在前台访问404.html界面

FreeMarker解析了404.html文件中我们插入的payload,导致命令执行

由于74CMS是基于Thinkphp3的语法魔改而成。建议先去大概看一下Thinkphp3的开发手册:http://document.thinkphp.cn/manual_3_2.html#

先来看一下漏洞代码:ThinkPHPLibraryThinkView.class.php

在第122行,include $templateFile 典型的文件包含,如果 $templateFile 可控就可以getshell。

通读 fetch() 函数代码,发现如果想要文件包含,传进来的参数 $content 必须为空,才能进入if循环与下面的三元表达式。把前端获取的 $templateFile 传进 parseTemplate() 方法:

啊...这?传进来的参数 $template 经过 is_file() 仅仅是做了文件是否存在以及是否为正常的文件,就直接把 $template return ...

当使用PHP原生模板时会进入下面的if循环,紧接着就 include $templateFile 。

什么是PHP原生模板?

由开发者手册可知,如果要使用PHP代码时尽量采用php标签,也就是 <php>...</php> 这种形式

大概知道这些,我们就可以通过上传内容为PHP原生模板的文件,再使用 include 包含。

继续回溯代码,寻找哪里调用 fetch() 这个函数,包括参数从哪里传过来

同文件下的 display() 方法里调用了fetch() 方法,看过模板手册的都知道,渲染模板输出最常用的是使用display方法,继续查找 display() 在哪里被调用

可以看到在 Controller.class.php 中有调用

直接在 MController.class.php 文件中就可以看到 display() 函数的调用

熟悉Tp框架的应该知道 I 方法时用来接收参数,而第20行 I('get.type'...) 说明 $type 可以通过get方式从前端获取

可见,这里将 $type 参数传入 display() 函数,display() 函数是 ThinkPHP 中展示模板的函数。然后又将参数传入 View 类的 display() 函数,最后调用 fetch() 函数,导致文件包含漏洞

使用自带的 favicon.ico 做下试验,看是否能成功包含:

成功包含。

如果想要包含我们构造的恶意文件,需要满足两个条件:

  1. 可以将恶意文件上传到服务器

  2. 有文件的绝对路径

注册一个账户,登录后台寻找文件上传的地方:

个人用户创建简历后支持上传 docx 格式的简历。上传一个内容为PHP原生模板的 docx 文件,将其作为模板。数据包如下:

上传文件的绝对路径为:/74cms_v4.1.5/upload/data/upload/word_resume/2009/14/5f5f8bdb56593.docx

再将这个文件名作为type的值,成功执行代码:

首先通过搜索关键字定位到导致漏洞的代码:coreviewView.php  ——>  parser()

根据payload,参数大概调用过程如上图

漏洞的关键点是 include $tpl_c_file,文件包含模板文件导致getshell。

parser() 方法接受传过来的模板文件 $file,经过 preg_replace() 方法来过滤掉相对路径(例如:https://www.cnblogs.com/bmjoker/,..),这里使用了不安全的替换,因为 preg_replace() 匹配到不安全的字符不是直接exit,而是选择替换成空,利用这个可以尝试构造绕过,像下图这样:

然后将替换过后的 $file 传入if 循环,第一个if判断 $file 是否是以 / 开头,第二个elseif判断 $file 是否包含 @ ,如果都不满足进入else拼接,$tpl_file = 模板路径 + / + $file

$tpl_file 是模板文件,$tpl_c_file 是要编译的文件。

继续看代码发现在121行又做了一次拼接,$tpl_c_file = 模板路径 + / + md5($tpl_file) + .php。紧接这是一个if判断,判断文件是否存在,判断 $tpl_c_file 文件的修改时间是否小于 $tpl_file,判断读取配置文件是否成功,很尴尬,全都是false,直接跳过if循环,到达关键地方,直接 include 包含我们构造的文件,导致漏洞产生。

这里可能有的人会有疑问,因为在到达 include 的时候,$tpl_c_file是 模板路径 + / + md5($tpl_file) + .php 这种形式,我们构造的文件路径早已面目全非。这个地方需要注意这个漏洞的根本原因是PbootCMS2.07内核处理缺陷导致的一个前台任意文件包含漏洞,他的内核函数在生成编译文件的时候造成任意文件读取。

parser() 方法已经分析完毕,现在需要寻找调用了parser函数的地方,且参数可控

进入 Controller.php 文件

这里看到显示模板,解析模板都有调用到 parser 方法,继续跟踪判断哪里调用

显示模板 display() 方法发现没有参数可控,但是解析模板 parser() 方法,发现有变量传入

先来看 SearchController.php 文件

index() 方法中,接收前端传递过来的参数,进入正则匹配,这正则匹配任意的字符,还包括-,.,/,最后直接传入 parser() 方法中,直接构造利用读取robots.txt:

同样构造利用的还有 TagController.php 文件

包含写入shell的txt文件:

最新文章
未来科技风潮深度探究十大高科技行业的创新趋势与商业机遇
未来科技风潮:深度探究十大高科技行业的创新趋势与商业机遇随着技术的飞速发展,全球范围内出现了众多高科技产业,这些行业不仅推动了经济增长,还极大地改变了人们的生活方式。以下是对十大高科技行业的一种分类和分析,其中包含了人工智
用Python爬虫技术怎么挣点小钱,这四种方法可行_python爬虫怎么挣钱
提醒:抓取的数据如果要商业化,要小心知识产权问题噢。还要提醒一点:抓取和处理这些数据的代价要小于人工处理的代价,使用爬虫代替人工才有价值。 我利用Python爬虫技术赚点小钱方式,在正式聊Python爬虫
怎么优化SEO?教你4步提高排名
怎么优化SEO?教你4步提高排名如果你想提高你的网站在搜索引擎结果页中的排名,那么你需要关注SEO。SEO搜索引擎优化指的是优化你的网站,以便更好地满足搜索引擎算法中的需求。在本文中,我们将为您介绍4个步骤,以帮助您提高SEO排名。第一
OpenAI推出ChatGPTCanvas:人工智能编程新纪元来临!
在一个激动人心的发布会上,OpenAI推出了ChatGPTCanvas,这一创新工具不仅革新了人与AI的互动方式,还极大地提升了人工智能在编程中的应用潜力。这次更新吸引了广泛关注,尤其是在程序员和技术爱好者中。ChatGPTCanvas的引入标志着人工智能
永久激活 ChatGPT 4o mini,有效期至2999年,我上车了!!!
大家好,这里是小镜智能AI小镜智能AI ChatGPT镜像站:https://xj.xiaozhi01.com/315扫描二维码也可进入小镜智能AI距离GPT-4的发布已经过去了一年,当地时间7月18日,OpenAI发布了新款模型GPT-4o-mini这次发布的既不是传了很久的搜索引擎,
杭州的证券公司排名是怎样的?第一名是
杭州股票的佣金一般是可以协商给到成本价的,各家券商营业部的开户交易手续费标准都不相同,申请开通低手续费的账户可以提前联系客户经理,股票开户建议您在网上操作办理,办理开户准备好您的身份证和一类银行卡就行。股票开户的流程如下:
邵阳天气预报?邵阳天气预报十五天 15天?
〖壹〗、湖南邵阳天气预报:3月8日(周三)阴转小雨,9~15℃,北风 1-2级,空气良。湿度:60%,紫外线强度:最弱,日出:06:51,日落:18:39。3月9日(周四)中雨,9~12℃,北风 1-2级,空气良。〖贰〗、邵阳双清区天气预报30天 双清天气预
谷歌将为Google Authenticator加入端到端加密
谷歌将为Google Authenticator加入端到端加密。Google Authenticator(身份验证器)是谷歌推出的基于时间的一次性密码(Time-based One-time Password),只需要在手机上安装该APP,就可以生成一个随着时间变化的一次性密码,用于帐户验证。G
推荐一款“微乐内蒙麻将开挂免费下载安装”(确实是有挂)-知乎
本篇文章给大家谈谈怎样看出手机打牌开挂没,以及手机麻将怎么看出来是开挂对应的知识点,希望对各位有所帮助,不要忘了收藏本站喔。无需打开直接搜索微信;1.打开手机桌面微信APP,进入微信主页。2.下拉微信主页,找到四川麻将小程序。注意
vivo智能手机常见问题解决方案大全
本帖最后由 海风一瓢 于 2014-11-21 19:41 编辑 崔勇 执念IT 码设置相关类1、忘记短信密码如何处理?智能机短信密码是没有默认密码的,您第一次设置的密码就是原始密码。如果您自己设置了密码忘记了的话,您可以在电脑端使用vivo助手备份相
相关文章
推荐文章
发表评论
0评