PHPCMS v9本地文件包含漏洞Getshell
时间:2023-04-20 22:48:01 | 来源:网站运营
时间:2023-04-20 22:48:01 来源:网站运营
PHPCMS v9本地文件包含漏洞Getshell:
漏洞原理
文件包含函数加载的参数没有经过过滤或者严格定义,可以被用户控制,包含了其他恶意文件,导致执行了非预期的代码。
漏洞危害
文件包含是指程序代码在处理包含文件的时候没有严格控制。导致用户可以构造参数包含远程代码在服务器上执行,并得到网站配置或者敏感文件,进而获取到服务器权限,造成网站被恶意删除,用户和交易数据被篡改等一系列恶性后果。主要包括本地文件包含和远程文件包含两种形式,由于开发人员编写源码,开放着将可重复使用的代码插入到单个的文件中,并在需要的时候将它们包含在特殊的功能代码文件中,然后包含文件中的代码会被解释执行。由于并没有针对代码中存在文件包含的函数入口做过滤,导致客户端可以提交恶意构造语句提交,并交由服务器端解释执行。
PHPCMS v9本地文件包含漏洞Getshell
全局搜索“include”关键字
追踪变量
/phpcms/modules/block/block_admin.php
向上追踪$str变量,判断$str是否可控:
注意到: $str = $tpl->template_parse(new_stripslashes($template));
向上追踪$template变量,判断$template是否可控:
全局搜索new_stripslashes()函数:
全局搜索template_parse()函数:
结论:$str变量为用户可控变量。
那么当恶意用户构造 template=');?> 时,经过文件写入再到文件包含,就能成功生成shell.php木马文件。
如何才能执行到这段代码?
必须$data['type']==2 漏洞才会产生。
而 $data = $this->db->get_one(array('id'=>$id))
全局搜索定义get_one()的地方:
发现2处,函数内容都一样:
$data = array('id'=>$id)
$table是由phpcms模块指定的。调用get_one()函数的文件是/phpcms/modules/block/block_admin.php,所以模块为block。即$table=block
下面即为block表及其相应的字段:
array_walk(数组,"myfunction"); —— 对数组中的每个元素使用用户自定义函数处理。在函数中,数组的键名和键值是参数。
例:
所以定位 add_special_char() 函数:
这个函数可以忽略掉。
所以最终SQL查询语句为:select id from phpcmsv9.v9_block limit 1;
定位 fetch_next() 函数:
使用 MYSQL_ASSOC 字符索引作为结果集。
所以要想 $data['type']==2 只需要 v9_block 表的某一行数据中的type字段的值为2即可。
那么如何向 v9_block 表中插入数据呢?
最终在/phpcms/modules/block/block_admin.php文件中找到向 v9_block 表中添加数据的函数体:
$_POST['name']的值在v9_block表中不存在时才会插入数据。
如何调用 add() 函数:
请求:
http://IP/index.php?m=block&c=block_admin&a=add&pos=任意值
发送数据包:dosubmit=任意值&name=v9_block表name字段不存在的值&type=2
还需要登录管理后台获取hash值:
提交第一个Payload,向数据库中插入数据:
查看数据库:
页面跳转到:
到这个页面时,就已经进入了/phpcms/modules/block/block_admin.php文件中,执行block_update方法了:
但我们需要执行 publi_view()方法进行文件包含:
所以在页面上查找是否有执行 publi_view() 方法模块,最终如下:
点击"预览"后会执行public_view()方法,在根目录下生成shell.php木马文件:
漏洞利用条件
1、block_admin.php需要登录认证管理员账号;
2、POST数据包中name值在v9_block表name字段中不存在;
3、POST数据包中type值必须为2。
Getshell:
修复建议
- PHP:配置php.ini关闭远程文件包含功能(allow_url_include = Off)
- 严格检查变量是否已经初始化。
- 建议假定所有输入都是可疑的,尝试对所有输入提交可能可能包含的文件地址,包括服务器本地文件及远程文件,进行严格的检查,参数中不允许出现../之类的目录跳转符。
- 严格检查include类的文件包含函数中的参数是否外界可控。
- 不要仅仅在客户端做数据的验证与过滤,关键的过滤步骤在服务端进行。
- 在发布应用程序之前测试所有已知的威胁。