您现在的位置是:首页 > cms教程 > phpcms教程phpcms教程
PHPCMSv9.6.1任意文件读取漏洞分析
春雁2025-05-15 16:35:38phpcms教程已有4人查阅
导读PHPCMS使用教程介绍PHPCMSv9.6.1任意文件读取漏洞的挖掘看到网上说出了这么一个漏洞,所以抽空分析了下,得出本篇分析。1.准备工作&漏洞关键点快速扫描
PHPCMS使用教程介绍PHPCMSv9.6.1任意文件读取漏洞的挖掘
看到网上说出了这么一个漏洞,所以抽空分析了下,得出本篇分析。
1.准备工作&漏洞关键点快速扫描
1.1前置知识
这里把本次分析中需要掌握的知识梳理了下:
php原生parse_str方法,会自动进行一次urldecode,第二个参数为空,则执行类似extract操作。
原生empty方法,对字符串""返回true。
phpcms中sys_auth是对称加密且在不知道auth_key的情况下理论上不可能构造出有效密文。
1.2快速扫描
先diff下v9.6.0和v9.6.1,发现phpcms/modules/content/down.php中有如下修改:
---a/phpcms/modules/content/down.php
+++b/phpcms/modules/content/down.php 主要修改了两个方法init()和download(),大胆的猜想估计是这两个函数出问题了。 safe_replace函数如下 1.2content/down模块大致流程分析
init方法中根据原始的$a_k(包含了file_down的文件的基本信息),进行一次验证,并且生成,调用
download方法的url,url的schema为$downurl='?m=content&c=down&a=download&a_k='.$a_k(必须符合条件。)
download方法接收到$a_k,进行解码,解出文件信息,调用file_down($fileurl,$filename)(必须符合条件)
我们来看下file_down函数,头一个参数$filepath,才是实际控制readfile的文件名的变量,readfile可以读取本地文件,所以我们构造符合条件的$fileurl绕过上述的限制就可以完成本地文件的读取功能! 1.2.1$fileurl变量构造分析
如果我们要读取站点的.php结尾文件,由于有关键点11存在,$fileurl中不能出现php,不过从关键点17可以看到进行了替换 那么可以想到我们构造出符合.ph([]+)p的文件后缀,最后会被替换成.php。而且这句话是9.6.1新增的,更加确定了,这个漏洞是9.6.1特有的。
再向上上看 变量$m为真,那么我们可以通过引入变量$s来构造$fileurl,且$fileurl由变量$f控制。 通过parse_str来extract变量,很容易的得出控制$i,$m,$f,$t,$s,$d,$modelid变量,看到这里我们可以构造$a_k来控制这些变量。
1.2.2$a_k变量分析
再向上看 这个关键点6很重要,因为这里的$pc_auth_key几乎是不可能暴力出来的,然而得到这个加密的$a_k只有在init()方法中使用了相同的$pc_auth_key。所以我们只能通过init()方法来构造$a_k。
我们现在来看下init方法 这里可以发现sys_auth的auth竟然是使用系统默认的auth_key,直觉告诉我可能问题出在这里了,除了这个区别,init方法别的逻辑就不再赘述。
1.2.3小结
总结一下:
index.php?m=content&c=down&a=init&a_k=想办法构造出符合条件的。
然后init方构造出符合download方法中能够解密的$a_k。
通过对$a_k进行控制,间接控制$i,$f,$m,$s,$d等变量完成漏洞的利用。
2.漏洞挖掘过程2.1init方法所接受的$a_k构造2.1.1探索正常流程中的$a_k构造过程
对源码进行快速扫描,看看哪些地方能够生产对init方法的调用,其实就是常规的下载模型的逻辑。
phpcms/modules/content/fields/downfile和phpcms/modules/content/fields/downfiles中会生成init方法的$a_k 但是分析发现,content_input和content_output逻辑中权限验证和限制逻辑比较完善,基本不存在利用可能。
2.1.2黑科技构造$a_k
由于是sys_auth是对称加密,那么能不能找个使用相同密钥生成的地方来生成,对sys_auth进行全文搜索,我们找找有没有符合下列条件的上下文
方式是ENCODE
Auth_key是系统默认的即:pc_base::load_config('system','auth_key')
且待加密内容是可控的(可以是我们$_REQUEST的数据,或者可以构造的)
加密后的数据有回显的。
共找到58个匹配项,但是没有符合上下文的,不过我们可以注意到 param::set_cookieparam::get_cookie对cookie加密是使用默认的auth_key的。
马上对set_cookie进行全文搜索,并且查找符合下列条件的上下文。
set_cookie的内容是可控的。
set_cookie的触发条件尽可能的限制小。
一共找到122个匹配项,找到了两个比较好的触发点。
phpcms/moduels/attachment/attachments.php中的swfupload_json/swfupload_del方法和phpcms/modules/video/video.php中的swfupload_json/del方法
video模块需要管理员权限,就不考虑了,attachment模块只要是注册用户即可调用。
我们来看下swfupload_json 我们可以通过src和filename来构造,最终我选的是src,最终形式会是一个json串,当然有多个会以"||"分割。
我们注册个用户登录之后,调用 产生的数据会是 然后我们得到response.header中的set-cookie["att_json"]。 我们修改下down.php->init方法,把DECODE之后的$a_k输出来。
然后我们调用 激动人心,init方法成功DECODE了$a_k
好了目前验证了我们的想法可行,接下来应该构造可用的payload了。
2.2json和parse_str
目前要解决的就是从json中parse_str并且能够解析出$i,$m,$f等变量。 解析 说明parse_str还是解析还是可以实现的,前后闭合一下,中间填充我们需要的变量即可,例如 那么fobnn和p1就是正常解析的,src需要URLENCODE提交,这样不会导致php解析错误。
2.3构造符合init方法的$a_k
我们先构造一个符合init方法的$a_k使得能完成正常的流程。 构造pad=x&i=1&modelid=1&m=1&catid=1&f=fobnn&pade=用来满足条件。 得到 然后提交 成功!页面已经生成了调用download方法的url 2.4绕过限制构造最终payload
目前正常流程已经走通,把目光集中在如何构造出符合的$fileurl,来看下init方法中 对f的限制还是蛮多的,包括常规黑名单检测php,asp等。也不能出现"..",":"
还好我们看到download函数中 我们可以通过控制$m就可以通过$s来构造了,而$m和$s参与了$a_k的构造。
在init方法中我们可以构造m=1&s=.php&f=index类似的来绕过init方法的检测,我们把目光聚焦到download方法。 通过这样的构造上面这个检测肯定可以绕过,但发现下面检测就会出问题,最后$fileurl还是会变成index.php 好在快速扫描中看到的 另外又看到 2.4.1urlencode编码“”
那么构造出 最终 由于safe_replce的存在所以
所以可以构造
d=1&m=1&f=.p%3chp&s=index
我们发现在init方法中会safe_replace一次,和parse_str一次。
那么最终编码到download$a_k中的数据实际还是
所以我们要确保在init方法编码的时候是%3c即可,对%3c进行一次urlencode,构造 当然要读取别的目录的,那同样对目录路径进行编码。
2.4.2最终payload
以读取首页index.php为例 最终提示下载文件,文件下载成功,打开来看确实是index.php内容。
2.5绕过attachment模块权限限制完成制利用 可以发现 可控制$this->userid且没有复杂的权限校验,而且又是默认AUTH_KEY加密的。
全文找下制可以set_cookie的,发现WAP模块可以利用 没有任何条件限制我们可以$_GET['siteid']来控制param::set_cookie('siteid',$this->siteid),且默认都有WAP模块的文件,但不需要开启。
3.EXP编写
流程如下:
index.php?m=wap&c=index&siteid=1获取名称为siteid的cookie。
访问index.php?m=attachment&c=attachments&a=swfupload_json&aid=1
&src=想要读取文件的payload,并且访问的时候设置post字段userid_flash为步骤一获取的cookie.
响应成功之后,获取名称为att_json的cookie
访问index.php?m=content&c=down&a=init&a_k=获取到的att_json,来构造最终漏洞利用路径,
可以直接截取生成的$a_k
访问index.php?m=content&c=download&a=init&a_k=截取的$a_k.完成利用。
4.修案
init方法中的$a_k加解密sys_auth不要采用默认密钥。
file_down之前对$fileurl再做一次过滤。
看到网上说出了这么一个漏洞,所以抽空分析了下,得出本篇分析。
1.准备工作&漏洞关键点快速扫描
1.1前置知识
这里把本次分析中需要掌握的知识梳理了下:
php原生parse_str方法,会自动进行一次urldecode,第二个参数为空,则执行类似extract操作。
原生empty方法,对字符串""返回true。
phpcms中sys_auth是对称加密且在不知道auth_key的情况下理论上不可能构造出有效密文。
1.2快速扫描
先diff下v9.6.0和v9.6.1,发现phpcms/modules/content/down.php中有如下修改:
---a/phpcms/modules/content/down.php
+++b/phpcms/modules/content/down.php 主要修改了两个方法init()和download(),大胆的猜想估计是这两个函数出问题了。 safe_replace函数如下 1.2content/down模块大致流程分析
init方法中根据原始的$a_k(包含了file_down的文件的基本信息),进行一次验证,并且生成,调用
download方法的url,url的schema为$downurl='?m=content&c=down&a=download&a_k='.$a_k(必须符合条件。)
download方法接收到$a_k,进行解码,解出文件信息,调用file_down($fileurl,$filename)(必须符合条件)
我们来看下file_down函数,头一个参数$filepath,才是实际控制readfile的文件名的变量,readfile可以读取本地文件,所以我们构造符合条件的$fileurl绕过上述的限制就可以完成本地文件的读取功能! 1.2.1$fileurl变量构造分析
如果我们要读取站点的.php结尾文件,由于有关键点11存在,$fileurl中不能出现php,不过从关键点17可以看到进行了替换 那么可以想到我们构造出符合.ph([]+)p的文件后缀,最后会被替换成.php。而且这句话是9.6.1新增的,更加确定了,这个漏洞是9.6.1特有的。
再向上上看 变量$m为真,那么我们可以通过引入变量$s来构造$fileurl,且$fileurl由变量$f控制。 通过parse_str来extract变量,很容易的得出控制$i,$m,$f,$t,$s,$d,$modelid变量,看到这里我们可以构造$a_k来控制这些变量。
1.2.2$a_k变量分析
再向上看 这个关键点6很重要,因为这里的$pc_auth_key几乎是不可能暴力出来的,然而得到这个加密的$a_k只有在init()方法中使用了相同的$pc_auth_key。所以我们只能通过init()方法来构造$a_k。
我们现在来看下init方法 这里可以发现sys_auth的auth竟然是使用系统默认的auth_key,直觉告诉我可能问题出在这里了,除了这个区别,init方法别的逻辑就不再赘述。
1.2.3小结
总结一下:
index.php?m=content&c=down&a=init&a_k=想办法构造出符合条件的。
然后init方构造出符合download方法中能够解密的$a_k。
通过对$a_k进行控制,间接控制$i,$f,$m,$s,$d等变量完成漏洞的利用。
2.漏洞挖掘过程2.1init方法所接受的$a_k构造2.1.1探索正常流程中的$a_k构造过程
对源码进行快速扫描,看看哪些地方能够生产对init方法的调用,其实就是常规的下载模型的逻辑。
phpcms/modules/content/fields/downfile和phpcms/modules/content/fields/downfiles中会生成init方法的$a_k 但是分析发现,content_input和content_output逻辑中权限验证和限制逻辑比较完善,基本不存在利用可能。
2.1.2黑科技构造$a_k
由于是sys_auth是对称加密,那么能不能找个使用相同密钥生成的地方来生成,对sys_auth进行全文搜索,我们找找有没有符合下列条件的上下文
方式是ENCODE
Auth_key是系统默认的即:pc_base::load_config('system','auth_key')
且待加密内容是可控的(可以是我们$_REQUEST的数据,或者可以构造的)
加密后的数据有回显的。
共找到58个匹配项,但是没有符合上下文的,不过我们可以注意到 param::set_cookieparam::get_cookie对cookie加密是使用默认的auth_key的。
马上对set_cookie进行全文搜索,并且查找符合下列条件的上下文。
set_cookie的内容是可控的。
set_cookie的触发条件尽可能的限制小。
一共找到122个匹配项,找到了两个比较好的触发点。
phpcms/moduels/attachment/attachments.php中的swfupload_json/swfupload_del方法和phpcms/modules/video/video.php中的swfupload_json/del方法
video模块需要管理员权限,就不考虑了,attachment模块只要是注册用户即可调用。
我们来看下swfupload_json 我们可以通过src和filename来构造,最终我选的是src,最终形式会是一个json串,当然有多个会以"||"分割。
我们注册个用户登录之后,调用 产生的数据会是 然后我们得到response.header中的set-cookie["att_json"]。 我们修改下down.php->init方法,把DECODE之后的$a_k输出来。
然后我们调用 激动人心,init方法成功DECODE了$a_k
好了目前验证了我们的想法可行,接下来应该构造可用的payload了。
2.2json和parse_str
目前要解决的就是从json中parse_str并且能够解析出$i,$m,$f等变量。 解析 说明parse_str还是解析还是可以实现的,前后闭合一下,中间填充我们需要的变量即可,例如 那么fobnn和p1就是正常解析的,src需要URLENCODE提交,这样不会导致php解析错误。
2.3构造符合init方法的$a_k
我们先构造一个符合init方法的$a_k使得能完成正常的流程。 构造pad=x&i=1&modelid=1&m=1&catid=1&f=fobnn&pade=用来满足条件。 得到 然后提交 成功!页面已经生成了调用download方法的url 2.4绕过限制构造最终payload
目前正常流程已经走通,把目光集中在如何构造出符合的$fileurl,来看下init方法中 对f的限制还是蛮多的,包括常规黑名单检测php,asp等。也不能出现"..",":"
还好我们看到download函数中 我们可以通过控制$m就可以通过$s来构造了,而$m和$s参与了$a_k的构造。
在init方法中我们可以构造m=1&s=.php&f=index类似的来绕过init方法的检测,我们把目光聚焦到download方法。 通过这样的构造上面这个检测肯定可以绕过,但发现下面检测就会出问题,最后$fileurl还是会变成index.php 好在快速扫描中看到的 另外又看到 2.4.1urlencode编码“”
那么构造出 最终 由于safe_replce的存在所以
所以可以构造
d=1&m=1&f=.p%3chp&s=index
我们发现在init方法中会safe_replace一次,和parse_str一次。
那么最终编码到download$a_k中的数据实际还是
所以我们要确保在init方法编码的时候是%3c即可,对%3c进行一次urlencode,构造 当然要读取别的目录的,那同样对目录路径进行编码。
2.4.2最终payload
以读取首页index.php为例 最终提示下载文件,文件下载成功,打开来看确实是index.php内容。
2.5绕过attachment模块权限限制完成制利用 可以发现 可控制$this->userid且没有复杂的权限校验,而且又是默认AUTH_KEY加密的。
全文找下制可以set_cookie的,发现WAP模块可以利用 没有任何条件限制我们可以$_GET['siteid']来控制param::set_cookie('siteid',$this->siteid),且默认都有WAP模块的文件,但不需要开启。
3.EXP编写
流程如下:
index.php?m=wap&c=index&siteid=1获取名称为siteid的cookie。
访问index.php?m=attachment&c=attachments&a=swfupload_json&aid=1
&src=想要读取文件的payload,并且访问的时候设置post字段userid_flash为步骤一获取的cookie.
响应成功之后,获取名称为att_json的cookie
访问index.php?m=content&c=down&a=init&a_k=获取到的att_json,来构造最终漏洞利用路径,
可以直接截取生成的$a_k
访问index.php?m=content&c=download&a=init&a_k=截取的$a_k.完成利用。
4.修案
init方法中的$a_k加解密sys_auth不要采用默认密钥。
file_down之前对$fileurl再做一次过滤。
本文标签:
很赞哦! (1)
上一篇:phpcms安全漏洞归类整理
下一篇:PHPCMS常用调用语法总结示例
暂无内容 |
暂无内容 |
相关文章
暂无内容 |
暂无内容 |
随机图文
phpcms缓存文件目录位置在哪
phpcms缓存文件在哪里?phpcms缓存文件在caches目录下。caches目录:缓存文件集中地,按模型和类别分文件夹存放。discuz不能登陆phpcms的几种解决方法
discuz不能登陆phpcms怎么办?discuz,ucenter,uchome修改密码 phpcms不能登陆的问题修正1、在UC后台更改密码后PC无法登陆的phpcms实现wap单页的方法
下面以添加“关于我们”这一单页为例进行说明:一、复制phpcms\templates\default\wap下的maps.html,粘贴重命名为about.html,并修改其中内容作为“关于我们”的模板文件;phpcms的getcache()函数有什么作用
一直没有去研究phpcms 的getcache()函数是干嘛的,今天有空去看了一下,原来就那样。getcache()就是获取缓存数据的,
留言与评论 (共有 0 条评论) |