先放漏洞函数,觉得太长无聊可以直接看后面

function docompare(){
        if(!empty($this->setting['check_useragent'])) {
            $this->load('anticopy');
            if(!$_ENV['anticopy']->check_useragent()){
                $this->message('禁止访问','',0);
            }
        }
        if(!empty($this->setting['check_visitrate'])) {
            $this->load('anticopy');
            $_ENV['anticopy']->check_visitrate();
        }
        if ($this->get[4] == 'box'){
            @header('Content-type: text/html; charset='.WIKI_CHARSET);
            if(!@is_numeric($this->get[2])||!@is_numeric($this->get[3])){
                $this->message($this->view->lang['parameterError'],'index.php',0);
            }
            $did = $this->get[2];
            $eid = $this->get[3];
            $edition = array(); 
            $editions=$_ENV['doc']->get_edition_list($did,'`time`,`authorid`,`author`,`words`,`images`,`content`', $eid);

            $this->view->assign('edition',$editions);
            $this->view->display('comparebox');
            exit;
        }
        if(@!is_numeric($this->post['eid'][0])||@!is_numeric($this->post['eid'][1])){
            $this->message($this->view->lang['parameterError'],'index.php',0);
        }
        $edition=$_ENV['doc']->get_edition(array_slice($this->post['eid'], 0, 2));
        if($edition[0]['did']!=$edition[1]['did']){
            $this->message($this->view->lang['parameterError'],'index.php',0);
        }
        $doc=$this->db->fetch_by_field('doc','did',$edition[0]['did']);
        $doc['rawtitle']=$doc['title'];
        if(@$doc['visible']=='0'&&!$this->checkable('admin_doc-audit')){
            $this->message($this->view->lang['viewDocTip4'],'index.php',0);
        }
        $edition[0]['tag']=$_ENV['doc']->spilttags($edition[0]['tag']);
        $edition[0]['editions']=$this->post['editions_'.$edition[0]['eid']];
        $edition[1]['tag']=$_ENV['doc']->spilttags($edition[1]['tag']);
        $edition[1]['editions']=$this->post['editions_'.$edition[1]['eid']];
        $doc['title']=$edition[0]['title'];
        $doc['did']=$edition[0]['did'];
        $this->view->assign('doc',$doc);
        $this->view->assign('edition',$edition);
        //$this->view->display('compare');
        $_ENV['block']->view('compare');
    }

我们注意到它这个操作:

if(@!is_numeric($this->post['eid'][0])||@!is_numeric($this->post['eid'][1])){
            $this->message($this->view->lang['parameterError'],'index.php',0);
        }
        $edition=$_ENV['doc']->get_edition(array_slice($this->post['eid'], 0, 2));

先是检查了 POST 的 eid 数组,键是 0、1 的值是否为数字,如果不是则报错退出
如果是数字的话,则选出数组中的前两个键值
我们知道,POST 传进去后,键不会自动排序的,传的时候是什么顺序,接收到的就是什么顺序,然而 array_slice 的第二个参数表示的是偏移量,那么它这里实际上选出的 POST 的 eid 数组的前两个键值,而不是键为 0、1 的键值,现在传入 get_edition 的参数是我们可控的了,跟进函数看看做了些啥

function get_edition($eid){
        $editionlist=array();
        if(is_numeric($eid)){
            $edition= $this->db->fetch_first("SELECT * FROM ".DB_TABLEPRE."edition WHERE eid=$eid");
            if($edition){
                $edition['comtime']=$edition['time'];
                $edition['time']=$this->base->date($edition['time']);
                $edition['rawtitle']=$edition['title'];
                $edition['title']=htmlspecial_chars($edition['title']);
                if(!$edition['content']){
                    $edition['content']=file::readfromfile($this->get_edition_fileinfo($edition['eid'],'file'));
                }
            }
            return $edition;
        }else{
            $eid=implode(",",$eid);
            $query=$this->db->query(" SELECT * FROM ".DB_TABLEPRE."edition WHERE eid IN ($eid)");
            while($edition=$this->db->fetch_array($query)){
                $edition['time']=$this->base->date($edition['time']);
                $edition['rawtitle']=$edition['title'];
                $edition['title']=htmlspecial_chars($edition['title']);
                if(!$edition['content']){
                    $edition['content']=file::readfromfile($this->get_edition_fileinfo($edition['eid'],'file'));
                }
                $editionlist[]=$edition;
            }
            return $editionlist;
        }
    }

这里很明显,如果传入的是数组,那么先整合成字符串,然后直接带入了sql查询语句中,那么这就造成了sql注入

影响如下:

源链接

Hacking more

...