### 简要描述: 过滤不严。 ### 详细说明: 在api/js.php中 ``` if($_SERVER['QUERY_STRING']) { $exprise = isset($_GET['tag_expires']) ? intval($_GET['tag_expires']) : 0; $moduleid = isset($_GET['moduleid']) ? intval($_GET['moduleid']) : 0; $moduleid > 3 or exit('document.write("<h2>Bad Parameter</h2>");'); $tag = $_SERVER['QUERY_STRING']; $_SERVER['QUERY_STRING'] = $_SERVER['REQUEST_URI'] = ''; foreach($_GET as $k=>$v) { unset($$k); } $_GET = array(); require '../common.inc.php'; header("Content-type:text/javascript"); ($DT['jstag'] && $DT['safe_domain'] && check_referer()) or exit('document.write("<h2>Invalid Referer</h2>");'); $tag = strip_sql(stripslashes(urldecode($tag))); foreach(array('#', '$', '&', 'table', 'fields', 'password', 'payword', 'debug') as $v) { strpos($tag, $v) === false or exit('document.write("<h2>Bad Parameter</h2>");'); } ob_start(); tag($tag, $exprise); ``` 在这里。($DT['jstag'] && $DT['safe_domain'] && check_referer()) or exit('document.write("<h2>Invalid Referer</h2>");');...
### 简要描述: 过滤不严。 ### 详细说明: 在api/js.php中 ``` if($_SERVER['QUERY_STRING']) { $exprise = isset($_GET['tag_expires']) ? intval($_GET['tag_expires']) : 0; $moduleid = isset($_GET['moduleid']) ? intval($_GET['moduleid']) : 0; $moduleid > 3 or exit('document.write("<h2>Bad Parameter</h2>");'); $tag = $_SERVER['QUERY_STRING']; $_SERVER['QUERY_STRING'] = $_SERVER['REQUEST_URI'] = ''; foreach($_GET as $k=>$v) { unset($$k); } $_GET = array(); require '../common.inc.php'; header("Content-type:text/javascript"); ($DT['jstag'] && $DT['safe_domain'] && check_referer()) or exit('document.write("<h2>Invalid Referer</h2>");'); $tag = strip_sql(stripslashes(urldecode($tag))); foreach(array('#', '$', '&', 'table', 'fields', 'password', 'payword', 'debug') as $v) { strpos($tag, $v) === false or exit('document.write("<h2>Bad Parameter</h2>");'); } ob_start(); tag($tag, $exprise); ``` 在这里。($DT['jstag'] && $DT['safe_domain'] && check_referer()) or exit('document.write("<h2>Invalid Referer</h2>");'); 绕过这个的话 只要safe domain里面有植就行 无论为什么。 然后check_referer 自己修改一下referer 就可以绕过了。 ``` function strip_sql($string) { $search = array("/union/i","/0x([a-z0-9]{2,})/i","/select([[:space:]\*\/\-])/i","/update([[:space:]\*\/])/i","/replace([[:space:]\*\/])/i","/delete([[:space:]\*\/])/i","/drop([[:space:]\*\/])/i","/outfile([[:space:]\*\/])/i","/dumpfile([[:space:]\*\/])/i","/load_file\(/i","/substring\(/i","/substr\(/i","/concat\(/i","/concat_ws\(/i","/ascii\(/i","/hex\(/i","/ord\(/i","/char\(/i"); $replace = array('union','0x\\1','select\\1','update\\1','replace\\1','delete\\1','drop\\1','outfile\\1','dumpfile\\1','load_file(','substring(','substr(','concat(','concat_ws(','ascii(','hex(','ord(','char('); return is_array($string) ? array_map('strip_sql', $string) : preg_replace($search, $replace, $string); } ``` 然后绕过这个的话 利用这里的deocode来绕过。 ``` function tag($parameter, $expires = 0) { global $DT, $CFG, $MODULE, $DT_TIME, $db; if($expires > 0) { $tag_expires = $expires; } else if($expires == -2) { $tag_expires = $CFG['db_expires']; } else if($expires == -1) { $tag_expires = 0; } else { $tag_expires = $CFG['tag_expires']; } $tag_cache = false; $db_cache = ($expires == -2 || defined('TOHTML')) ? 'CACHE' : ''; if($tag_expires && $db_cache != 'CACHE' && strpos($parameter, '&page=') === false) { $tag_cache = true; $TCF = DT_CACHE.'/tag/'.md5($parameter).'.htm'; if(is_file($TCF) && ($DT_TIME - filemtime($TCF) < $tag_expires)) { echo substr(file_get($TCF), 17); return; } } $parameter = str_replace(array('&', '%'), array('', '##'), $parameter); parse_str($parameter, $par); if(!is_array($par)) return ''; $par = dstripslashes($par); extract($par, EXTR_SKIP); isset($prefix) or $prefix = $db->pre; isset($moduleid) or $moduleid = 1; if(!isset($MODULE[$moduleid])) return ''; isset($fields) or $fields = '*'; isset($catid) or $catid = 0; isset($child) or $child = 1; isset($areaid) or $areaid = 0; isset($areachild) or $areachild = 1; isset($dir) or $dir = 'tag'; isset($template) or $template = 'list'; isset($condition) or $condition = '1'; isset($group) or $group = ''; isset($page) or $page = 1; isset($offset) or $offset = 0; isset($pagesize) or $pagesize = 10; isset($order) or $order = ''; isset($showpage) or $showpage = 0; isset($showcat) or $showcat = 0; isset($datetype) or $datetype = 0; isset($target) or $target = ''; isset($class) or $class = ''; isset($length) or $length = 0; isset($introduce) or $introduce = 0; isset($debug) or $debug = 0; isset($lazy) or $lazy = 0; (isset($cols) && $cols) or $cols = 1; if($catid) { if($moduleid > 4) { if(is_numeric($catid)) { $CAT = $db->get_one("SELECT child,arrchildid,moduleid FROM {$db->pre}category WHERE catid=$catid"); $condition .= ($child && $CAT['child'] && $CAT['moduleid'] == $moduleid) ? " AND catid IN (".$CAT['arrchildid'].")" : " AND catid=$catid"; } else { if($child) { $catids = ''; $sql="SELECT arrchildid FROM {$db->pre}category WHERE catid IN ($catid)"; echo $sql;exit; ``` 在这里 把语句输出来。 测试一下语句。 ### 漏洞证明: [<img src="https://images.seebug.org/upload/201404/0420513556a0426261f431e976228b6e05609c12.jpg" alt="d1.jpg" width="600" onerror="javascript:errimg(this);">](https://images.seebug.org/upload/201404/0420513556a0426261f431e976228b6e05609c12.jpg) 需要把referer修改成域名才能绕过check_referer 这里decode 那就用%2b来绕过空格。 过滤了substr 那就left 。 过滤了char 但是char (97)这样依旧可以执行。 基本就绕完了。 [<img src="https://images.seebug.org/upload/201404/04205326138f76190f16233c710ef56f05d6b86a.jpg" alt="d2.jpg" width="600" onerror="javascript:errimg(this);">](https://images.seebug.org/upload/201404/04205326138f76190f16233c710ef56f05d6b86a.jpg) 相等即执行。