思路整理并详细说明了一下
01
用户登陆判断的地方admin/global.php
在用户不存在地方呢执行了一个eval():
eval(base64_decode("Y$webdb[_Notice]"));
该参数打印出来:
copy("http://www.php168.com/Notice/?url=$webdb[www_url]",PHP168_PATH."cache/Notice.php");
将一个地址写入了Notice.php。那如果把这个地址变成一句话呢?
看一下,这个参数是否是可以修改利用的。
02
admin/center.php文件中
elseif($action=="config"&&($Apower[center_config]||$Apower[center_cache]||$Apower[user_reg])) { if($webdb[NewsMakeHtml]==1 && $webdbs[RewriteUrl]==1){ showmsg('你已经选择了真静态,就不能选择伪静态,要使用伪静态,请先取消真静态!!'); } if($ifmakeindexhtml=='N') { $webdbs[MakeIndexHtmlTime]=0; } elseif($ifmakeindexhtml=='Y'&&$webdbs[MakeIndexHtmlTime]<1) { $webdbs[MakeIndexHtmlTime]=700; } //当取消静态的时候,把首页重命名,不影响访问 if(isset($webdbs[MakeIndexHtmlTime])&&!$webdbs[MakeIndexHtmlTime]&&$webdb[MakeIndexHtmlTime]) { $rs=$db->get_one("SELECT htmlname FROM {$pre}channel WHERE id=1"); @unlink(ROOT_PATH."index.htm.bak"); rename(ROOT_PATH."$rs[htmlname]",ROOT_PATH."index.htm.bak"); } //当更换风格后,如果是首页静态的,要删除他,不然的话看不到效果 if( $webdb[MakeIndexHtmlTime] && isset($webdb[style]) ) { $rs=$db->get_one("SELECT * FROM {$pre}channel WHERE id=1"); if($webdb[style]!=$webdbs[style] || $index_style!=$rs[style]) { @unlink(ROOT_PATH."index.htm.bak"); rename(ROOT_PATH."$rs[htmlname]",ROOT_PATH."index.htm.bak"); } } if( isset($index_style) ) { $db->query("UPDATE {$pre}channel SET style='$index_style' WHERE id=1"); } if( isset($webdbs[copyright]) ) { $webdbs[hideFid]=$hideFid; } write_config_cache($webdbs); jump("修改成功",$FROMURL); }
在最后,调用了write_config_cache($webdbs);
这个函数在admin/global.php中,
//更新核心设置缓存 function write_config_cache($webdbs) { global $db,$pre; if( is_array($webdbs) ) { foreach($webdbs AS $key=>$value) { if(is_array($value)) { $webdbs[$key]=$value=implode(",",$value); } $SQL2.="'$key',"; $SQL.="('$key', '$value', ''),"; } $SQL=$SQL.";"; $SQL=str_Replace("'),;","')",$SQL); $db->query(" DELETE FROM {$pre}config WHERE c_key IN ($SQL2'') "); $db->query(" INSERT INTO `{$pre}config` VALUES $SQL "); } $writefile="\r\n"; $query = $db->query("SELECT * FROM {$pre}config"); while($rs = $db->fetch_array($query)){ if($rs[c_key]=='copyright1'){ $copyright1=$rs[c_value]; }elseif($rs[c_key]=='copyright2'){ $copyright2=$rs[c_value]; }else{ $rs[c_value]=addslashes($rs[c_value]); $writefile.="\$webdb['$rs[c_key]']='$rs[c_value]';\r\n"; } } write_file(ROOT_PATH."data/config.php",$writefile); if(!is_writable(ROOT_PATH."data/config.php")){ showmsg(ROOT_PATH."data/config.php文件目录权限不可写,请仔细检查"); } }
此函数通过遍历参数 $webdbs (数组),取其键值然后拼装给$SQL2 变量。
然后通过
$db->query(" DELETE FROM{$pre}config WHERE c_key IN ($SQL2'') "); 对这些key的值删除;
通过$SQL.="('$key', '$value', ''),";//对需要插入的数据打包处理,然后再通过
$db->query(" INSERT INTO`{$pre}config` VALUES $SQL "); //进行插入。
在此之前未对无法配置的_Notice 进行过滤。
那么就可以直接修改post包插入更新其值了。
03
但有一点,要想利用这个漏洞,需要先登入后台,在后台,有一个全局参数设置
Burpsuite抓包,并插入_Notice参数的内容
回到登陆页面使用错误的用户名登陆,返回
修改成功并执行了该语句,cache目录下生成了notice.php
尝试将身份认证的cookie删掉,执行,返回的是登陆页面,故需要先后台登陆或管理员cookie。
04
再说一下参数值的构造:
参见:http://0day5.com/archives/2690/
@——@偷个懒