大概是倒数的php CMS漏洞复现审计文章了…
youdiancmsv9.0
上次一个项目遇到了该cms二开之后的系统,注释里面标明了是该系统,v9.2的,当时下载了源码去审,没有审出来东西,找了不少低版本的poc,都没打成功,那就先审审低版本的,争取把新版本的给拿下来。
write webshell
漏洞点位于后台模板管理-》任一模板文件
App\Lib\Action\Admin\TemplateAction.class.php#68
先调用了YdInput类中的checkFileName
方法对传入的文件名进行了处理,跟进,代码很短,检查文件名不能出现的特殊字符并且替换为空
static function checkFileName($str){
$str = str_replace('..', '', $str);
return $str;
}
接着调用ltrim
方法去除文件名开头的空白字符之后拼接成完整的文件路径,接着调用了本类中的isValidTplFile
方法对模板文件进行校验;可以看到主要的手段就是通过限制文件名的后缀,先进行大小写转换之后再进行白名单检测
后面会调用htmlspecialchars_decode
进行实体编码的解码,这里不影响写入的shell
,然后就是调用file_put_contents
将文件的所有内容写入到模板文件当中;写入的html
文件本身就会被包含,所以其中的php
代码就会被php
解析器执行
Kitecms
write webshell
以前打比赛的经验,搜索危险函数,file_put_contents
,这里定位到了这个位置
application\admin\controller\Template.php#25
调用Request类中的param
方法进行获取path
参数,这里实例化了Site
类的对象赋值给了$siteObj
参数,并且调用了类中的方法去数据库中进行查询,这里$template
的值从数据库中取到值为default
经过处理之后的$rootpath=root_path/theme/default/$path
,root_path
的值为即是网站根目录下,$path
路径为可控点
if (!file_exists($rootpath) && !preg_match("/theme/", $rootpath)) {
throw new HttpException(404, 'This is not file');
}
这里对处理之后的路径进行校验,必须存在并且路径中包含有/theme/
,不然就会抛出相应的异常
接着往下
POST有传参就满足条件,接着会调用is_write
方法对指定路径下的文件进行可写权限判断,如果可写就会调用file_put_contents
方法,将调用htmlspecialchars_decode
方法进行实体解码之后的输入内容写入到$rootpath文件当中,实体解码对于我们的shell
并没有影响,并且前面对路径进行了拼接处理,这里就可以进行路径穿越将shell
写入到指定的文件当中去
poc
POST /admin/template/fileedit HTTP/1.1
Host: localhost
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:95.0) Gecko/20100101 Firefox/95.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Accept-Encoding: gzip, deflate
Referer: http://localhost/admin/template/fileedit
Content-Type: application/x-www-form-urlencoded
Content-Length: 44
Origin: http://localhost
Connection: close
Cookie: PHPSESSID=r0mbjo57rneu1l81c79rbf12e0
Upgrade-Insecure-Requests: 1
Sec-Fetch-Dest: document
Sec-Fetch-Mode: navigate
Sec-Fetch-Site: same-origin
path=../../index.php&html=<?php phpinfo();?>
any file reading
application\admin\controller\Template.php
还是一样的位置,接着往下看
只要不是以post
传参,就会校验指定文件可读权限,如果可读就会调用file_get_contents
读取,这里一样可以结合目录穿越进行任意文件读取
poc
?path=../../filename
upload getshell
系统=>上传处这里可以增加上传的图片类型,之前的小结文章中也有提到过这种getshell的后台
之后看到站点=》新建,这里可以开启新建文件,并且可以上传文件,之后抓包跟进代码
application\admin\controller\Upload.php
Request类中的file方法获取到上传的文件的所有信息,后面实例化UploadFile类并调用类中的upload方法,跟进
application\common\model\UploadFile.php#127
,根据传入的fileType=image,只看相关的代码就可以了,这里先看一下默认的图片上传配置
config\site.php
中的默认配置没有更改,前面增加的上传后缀php实际上是有生效的
接着跟进check方法,thinkphp\library\think\File.php#226
可以看到这里判断判断条件为或,只要有一个为true
那么就会为真,而我们的目的是返回true,也就是if条件判断不能成立;这里$rule
数组中只有两个键值对,而文件大小是肯定满足的,所以只需要检查后缀就可以了,这里通过调试输出,$rule['ext'] == 'jpg,png,gif,php'
,上传php
文件肯定是成立的,所以下面只需要跟进checkImg
方法
这里还是要返回值为true
,因为上传的文件后缀是php
,所以肯定不在数组中,第一个in_array
返回值为false
,这里为与逻辑,所以if
判断恒不成立,返回true
,所以最后check
方法返回true
,那么shell
文件就上传成功了
PS
youdianCMS一直在更新中,漏洞均已修复;kitecms已经挺多年没有更新了,官网关站,文中的漏洞均在GitHub的issue中,作者已知悉但未推出迭代版本并且没有使用群体。
- 本文作者: joker
- 本文来源: 奇安信攻防社区
- 原文链接: https://forum.butian.net/share/1063
- 版权声明: 除特别声明外,本文各项权利归原文作者和发表平台所有。转载请注明出处!