这次的漏洞是出在默认的插件小说插件里,虽然有这个文件但是并没有安装,如果不安装的话,是没有这个表段的,所以说我们需要安装一下这个插件。然后查看数据库是不是多了一个表名为,XXXX_bookfeedback。

详细安装教程:【传送门

这里我就不演示安装了,我们开始看代码

漏洞文件:/plus/bookfeedback.php

首先看这个函数,这个函数的主要作用就是获取书的内容,如书名等,此处不存在注入漏洞

function GetOnebook($aid)
{
    global $dsql,$title;
    $aid = trim(preg_replace('#[^0-9]#i','',$aid));
    $reArr = array();

    $nquery = "Select * From `#@__story_books` where bid='$aid' ";
    
    $arcRow = $dsql->GetOne($nquery);
    if(!is_array($arcRow)) {
        return $reArr;
    }
    $reArr = $arcRow;
    $reArr['bid']    = $aid;
    $reArr['arctitle'] = $arcRow['bookname'];
    $title = $arcRow['bookname'];
    //$reArr['arcurl'] = GetFileUrl($aid,$arcRow['typeid'],$arcRow['senddate'],$reArr['bookname '],$arcRow['ismake'],$arcRow['arcrank'],$arcRow['namerule'],
    //$arcRow['typedir'],$arcRow['money'],$arcRow['filename'],$arcRow['moresite'],$arcRow['siteurl'],$arcRow['sitepath']);
    return $reArr;

}

256-266行

elseif ($comtype == 'reply')
    {
        $row = $dsql->GetOne("Select * from `#@__bookfeedback` where id ='$fid'");
        $arctitle = $row['arctitle'];
        $aid =$row['aid'];
        $msg = $quotemsg.$msg;
        $msg = HtmlReplace($msg,2);
        $inquery = "INSERT INTO `#@__bookfeedback`(`aid`,`typeid`,`username`,`arctitle`,`ip`,`ischeck`,`dtime`,`mid`,`bad`,`good`,`ftype`,`face`,`msg`)                 VALUES ('$aid','$typeid','$username','$arctitle','$ip','$ischeck','$dtime','{$cfg_ml->M_ID}','0','0','$feedbacktype','$face','$msg')";
        $dsql->ExecuteNoneQuery($inquery);
    }

这里是个引用回复的地方 首先进入这个If判断需要让$comtype的值为reply,这个很简单 Get 或者 Post数组中有一个键名是comtype内容是reply即可,然后下面是一个SQL语句,$fid此处也不存在注入漏洞,然后赋值,把表段arctitle字段的值赋值给$arctitle,然后aid字段赋值给$aid $msg进行了一下拼接,然后下方过滤了一下。这里其实是存在一个二次注入漏洞的,因为$row['arctitle']取出是没有做任何过滤的,直接取出来,aid是数字型 根本带不进去单引号。因为plus目录默认转义是addslashes()函数,导致单引号可以直接写入数据库,然后在取出的时候并没有做过滤导致单引号截断。但是这个地方是设置书名的地方,也就是说这里是书的名字,只能在后台设置,难道说这是一个毫无作用的后台注入? 不存在的,在引用回复的上面还有一段代码,如下。

239-254行

if($comtype == 'comments')
    {
        $arctitle = addslashes($arcRow['arctitle']);
        $arctitle = $arcRow['arctitle'];
        if($msg!='')
        {
            $inquery = "INSERT INTO `#@__bookfeedback`(`aid`,`catid`,`username`,`arctitle`,`ip`,`ischeck`,`dtime`, `mid`,`bad`,`good`,`ftype`,`face`,`msg`)                    VALUES ('$aid','$catid','$username','$bookname','$ip','$ischeck','$dtime', '{$cfg_ml->M_ID}','0','0','$feedbacktype','$face','$msg'); ";
            $rs = $dsql->ExecuteNoneQuery($inquery);
            if(!$rs)
            {
                echo $dsql->GetError();
                exit();
            }
        }
    }

老样子,Get 或者 Post数组中有一个键名是comtype内容是comments即可,然后就是一个没有任何用处的过滤,为什么没有用我们都知道,当然即使有用也不影响我们二次注入,上来addslashes()函数转义了$arcRow['arctitle']并赋值给$arctitle然后又给$arctitle赋值$arcRow['arctitle']所以说没有任何用,然后就是一个判断 判断$msg是否为0,这个也是用默认变量注册进入循环,这个地方的SQL语句其实根本就没有用到$arctitle变量,这是一个INSERT INTO语句,给$@__bookfeedback表写入内容的,这里可以看到arctitle的字段位置写入的是$bookname,我们只需要用变量注册写入一个单引号,默认的addslashes函数会直接转义成\’然后写入数据库就是一个单引号了’,之后再引用评论的时候引用一下就可以达到二次注入的效果,如下。

PayLoad1:http://WebSite/plus/bookfeedback.php?action=send&aid=1&fid=1&comtype=comments& validate=code!&fid=1&isconfirm=yes&bookname=’1111 Good Luck &msg=11111

validate为验证码&bookname为注入的内容 ,访问后

图片2.png

然后我们直接点击引用,输入框随便输入即可。看一下MySQL监控,自己搞的一个小工具

TIM图片20171225095642.png

成功写入单引号截断,爆管理员用户名密码的EXP我就不发了,反正肯定能爆出来。爆不出来我们也不会发出来这个漏洞。

PS:对于本次的Dede织梦CMS的审计,还有大概2-3个高危漏洞,大家可以关注我们的公众号:安云信息

*本文原创作者:山东安云