finecms任意文件写入从漏洞分析到exp编写到对接FOFA 批量检测
没有phpstorm,用notepad直接调试吧。
哈哈哈~
代码审计还是phpstorm看着比较舒服,而且IDE可以调试~
面对一个陌生的cms,首先就要了解他的大致程序架构。有phpstorm的话可以导入项目,如果是其他的文本编辑器可以用tree命令看下大致的目录接口,增强自己对程序功能的理解。
好了,不多提了。这里我们步入正题~
finecms/dayrui/controllers/Api.php data2 我的测试版本是V5.0.8
这个应该是和用户管理功能相关的函数。
漏洞出现在正则获取的地方没有对文件后缀严格判断,导致了image后面的值可控。这个是更新头像的功能~
我们来看看怎么形成的。
$uid = (int)$_REQUEST['uid']; $file = $_REQUEST['file'];
定位$file,从外部的REQUEST请求获取。
传递到preg_match的时候用正则去取$file传进来的值,没有过滤。那么我们构造的参数不是像正常用户那样传递图片类型呢?
正常用户:
file=data:image/jpeg;base64,PD9waHAgcGhwaW5mbygpOz8+
黑客:
file=data:image/php;base64,PD9waHAgcGhwaW5mbygpOz8+
那么我们构造文件名和注入恶意的php代码之后要怎么找到它上传后的路径呢?
看这里:
这里的uid应该是用户的id号,也是用的REQUEST请求接收。
同样可控,那么我们可以传递uid=1传入。那么这时候的dir为member/1/
文件名固定为:0x0.php
SYS_UPLOAD_PATH我们可以向上翻,看它继承于哪个类。这里它集成于M_Controller,我们查找这个文件就可以获知SYS_UPLOAD_PATH的值为:
还有一种土办法,就是用sublime text搜索
那么我们获得到上传文件的路径为:uploadfile/member/1/0x0.php
这时候的payload为:
uid=1&file=data:image/php;base64,PD9waHAgcGhwaW5mbygpOz8+
这只是局部的payload,还需要部分的鉴权。
我们从这个函数的开始的地方(115行)看起。
129行这里判断$data数组不为空
接下来我们得要绕过SYSKEY认证才能进入更新头像的函数
SYSKEY哪儿来了呢?看这段代码
从http头里面找~~
只要访问首页就能获取了,所以这里的鉴权形同虚设。
这里我们构造payload:
index.php?c=api&m=data2&auth=50ce0d2401ce4802751739552c8e4467¶m=update_avatar
即使用api.php下的data2方法,auth传递的参数为SYSKEY的值,然后传递update_avatar更新头像。
我们得到最终的payload为:
不同的版本返回不同但是测试了<=V5.0.8版本基本成功。
可能返回如下:
或者:
每次 获取SYSKEY又是很麻烦,分析了一下,很多站长对没有改安全码的,所以安全码基本都是固定的。
V5.0.11以下版本常见的SYSKEY值为:
820686a208b89d4c2f8b6f2622eff83e
202cb962ac59075b964b07152d234b70
50ce0d2401ce4802751739552c8e4467等。以上的是经过hash过的。
未hash过的SYSKEY在config目录的system.php文件里。
刚开始我从system.php文件里直接取出来用,结果就失败了。
后面发现原来SYSKEY的加密方式是md5(md5($pass)),取出来还要hash一次。
如果提示安全码错误的的话就去首页获取。
根据payload用fofa客户端写PoC(懒得用python了,这个类型的PoC方便)
思路是第一次发送post请求写入文件第二次请求访问