【exploit系列SYNACKTIV】Elfinder:Web端文件管理器的漏洞发现之旅
2023-4-19 10:55:0 Author: xz.aliyun.com(查看原文) 阅读量:36 收藏

文章分类:PHP漏洞利用分析

翻译来源:https://www.synacktiv.com/en/publications/elfinder-the-story-of-a-repwning.html

最近我们发现了elFinder软件中的路径遍历问题,该漏洞被分配了CVE-2022-26960。虽然此漏洞类型比较常见,但其发现的故事却非常有趣。在这里需要继续阅读以了解详细信息。

elFinder软件的这个严重的漏洞问题一直存在,在2019年,我们公司Synacktiv已经参与了一些漏洞的研究,Thomas Chauchefoin披露了一个该产品的命令注入问题。

因此,在我们的安全测试中,它经常是我们测试的重点之一,有时我们会发现一些意外的漏洞。

情况发现

几个月前,我们公司在常规的入侵渗透测试过程中,使用目标应用程序的wordlists对目标的根目录进行fuzz测试,测试结果结果引起了我们的兴趣。

000017052:   301        9 L      28 W       321 Ch      "elfinder"

在访问我们发现的目录后,我们发现了一个 elFinder Web管理器的部署。点击几下后,发生了令人惊异的事情:版本居然老版本2.1.12,版本非常古老!(2016年的版本)。

Thomas在2019年发现的CVE问题中是关于影响了2.1.48之前的所有版本,所以我们的2.1.12版本也是可以使用的,所以我们应该进入方向从命令注入走向RCE,接下来,如果我们阅读了有关CVE-2019-9194的报告,发现了一些微妙的细节:

其中$volume->resize()的实现可以在elFinder/php/elFinderVolumeDriver.class.php中找到,并且会执行各种操作确保调整大小可以不会显式禁用。

在我们的例子中,禁用了调整大小的功能,防止了攻击利用。然而,在这样一个旧版本中,那么就会因为未升级的带有的其他问题。但是事实上这样的问题是存在多个的。

CVE-2018-9109可以发现允许读取任意文件的路径遍历,也可以删除它,对我们的生产环境不太好。

所以,你可以在CVE-2021-32682和CVE-2021-23394中发现SonarSource的报告,并且漏洞发现者仍然是Thomas Chauchefoin。如果你还没有度过他的两篇文章的话,我建议你去看看。其中的TL和DR是一个有趣的漏洞列表,https://www.synacktiv.com/en/publications/elfinder-the-story-of-a-repwning.html#references,可以造成下面非常严重的影响:

  • 文件删除
  • 文件移动
  • PHP文件上传到远程代码执行
  • zip用户界面参数注入到远程代码执行
  • 竞争条件到远程代码执行

事实上,如果我们的产品不具备软件更新的条件,就做一流服务器的加固:

  • 在web的根目录没有写入权限
  • 在elFinder上传目录禁用PHP文件渲染和解析
  • 最小化部署,不使用zip CLI

此时我们没有了一个容易利用的方法

提示:如果你曾经怀疑投资是必需的,这会导致你变得错误。

接下来发生的事就像一个大骗局,像一个漏洞抢劫,可能也是意外的好运。

关于elFinder特点

如果你不熟悉我们所讨论的软件,他的特点是上传和下载文件,解压他们,预览诸如此类的功能。Web文件管理器是一个非常常见的Web应用程序,常常用于帮助用户上传、下载、编辑、删除和查看他们在Web服务器上存储的文件。然而,这些应用程序经常被安全研究人员和黑客用来寻找安全漏洞,因为它们可以直接操作Web服务器上的文件系统,从而可能导致危险的攻击行为。

Web文件管理器的安全漏洞案例研究:

  1. ElFinder:2016年,安全研究员发现一个严重的远程代码执行漏洞,漏洞编号为CVE-2016-4971[1]。该漏洞允许攻击者通过发送恶意POST请求来执行任意的PHP代码,并获取完全的服务器控制权。此漏洞影响多个版本的ElFinder,直到更新版本2.1.48为止。
  2. FileRun:2020年8月,FileRun被爆出拒绝服务(DoS)漏洞,并被CVE-2020-16479加以记录[2]。该漏洞利用了未经检查的输入来导致基于SQLite的数据库查询失败,从而导致服务器资源耗尽,拒绝服务攻击。
  3. OpenDocMan:2021年1月,研究人员发现一个目录遍历漏洞,利用此漏洞可以访问服务器上的私有文件和敏感信息[3]。该漏洞影响OpenDocMan 1.3.7版本及之前版本。
  4. AjaXplorer:2013年,安全研究员曝光了一个文件包含漏洞,允许攻击者读取服务器上的任意文件,并可能导致远程代码执行漏洞[4]。该漏洞影响AjaXplorer 4.0.4及之前版本。

关于代码流程处理

让我们想象我们在2010年开发一个软件,这个软件没有被广泛的审查。让我们看看我们面对的一个处理文件路径的软件,为了完成这个功能,想象我们想要测试路径的穿越问题。第一种一般的行为是用长的../字符提供给应用,然后尝试到达/etc/passwd 用这种方式。

如果我们提供的绕过方式不起作用,添加一些二次编码,编码关键词字符等等。

但是如果使用这种方式还是不成功呢?不在一个6年的老版本中。没有一个软件被有能力的人复查和检查过。

事实就是我们所尝试的。

等等?结果真的绕过了?

情绪过山车

发现利用点

我们发现我们在一种情况,这种情况下我们有一个意外看到的漏洞,并且没有办法,关于为什么是在这里,如此长得时间都没有人知道?然而,如果我们分析我们的paylaod,出现的是这个应用程序可能在处理../并且尝试删除他们。这种情况常在CTF中出现。

在我们的幸运纸上,让我们查找字符串".."。

$ find . -name "*.php" -exec grep -HF ".." {} \;
./elFinderVolumeDriver.class.php:    * System Root path (Unix like: '/', Windows: '\', 'C:\' or 'D:\'...)
./elFinderVolumeDriver.class.php:                           $name = preg_replace('/^(.*?)(\..*)?$/', '$1_'.$files[$name]++.'$2', $name);
./elFinderVolumeDriver.class.php:                           $name != '.' && $name != '..' && $this->rmTmb($this->stat($p));
./elFinderVolumeDriver.class.php:           if (substr($path, 0, 3) === '..' . $separator) {
./elFinderVolumeDriver.class.php:           // normalize `/../`
./elFinderVolumeDriver.class.php:                                   if ($file === '.' || $file === '..') {
./elFinderVolumeDriver.class.php:                           if ($file !== '.' && $file !== '..') {
./elFinderVolumeDriver.class.php:                                                           if ($entry !== "." && $entry !== "..") {
./elFinderVolumeDriver.class.php:    * Ususaly used for images, but can be realize for video etc...
./elFinderVolumeFTP.class.php:              if (count($info) < 9 || $info[8] == '.' || $info[8] == '..') {
./elFinderVolumeFTP.class.php:                      if (($comp != '..')
./elFinderVolumeFTP.class.php:                      || ($new_comps && (end($new_comps) == '..'))) {
./elFinderVolumeFTP.class.php:                      if ($name && $name !== '.' && $name !== '..' && substr(strtolower($info[0]), 0, 1) === 'd') {
./elFinderVolumeFTP.class.php:       * Ususaly used for images, but can be realize for video etc...
./elFinderVolumeFTP.class.php:                      if ($name !== '.' && $name !== '..' && (!$targets || isset($targets[$name]))) {
./elFinderVolumeFTP.class.php:              $excludes = array(".","..");
./elFinderVolumeLocalFileSystem.class.php:                  if (($comp != '..')
./elFinderVolumeLocalFileSystem.class.php:                  || ($new_comps && (end($new_comps) == '..'))) {
./elFinderVolumeLocalFileSystem.class.php:   * Usualy used for images, but can be realize for video etc...
./elFinderVolumeDropbox.class.php:   * Ususaly used for images, but can be realize for video etc...
./elFinderVolumeMySQL.class.php:     * Usualy used for images, but can be realize for video etc...

这里可以发现出现了很多结果。甚至更少的是如果我们目标是elFinderVolumeFTP, elFinderVolumeDropboxelFinderVolumeMySQL ,很可能没有什么起作用对我们的问题。所有的这些结果,一个代码评论可能捕捉这个眼睛。

./elFinderVolumeDriver.class.php: // normalize /../

跟着路径导致的getFullPath函数,从elFinderVolumeDriver类中发现。这个抽象类实现了一个通用组件,可以被使用,使用drivers调用,抽象文件从安坐,为不同的源类型。我们说我们仅仅考虑本地文件例子,所以让我们不用为此烦恼了。

/**
    * Resolve relative / (Unix-like)absolute path
    *
    * @param string $path  target path
    * @param string $base  base path
    * @return string
    */
protected function getFullPath($path, $base) {
    [...]
    // normalize `/../`
    $normreg = '#('.$sepquoted.')[^'.$sepquoted.']+'.$sepquoted.'\.\.'.$sepquoted.'#'; // '#(/)[^\/]+/\.\./#'
    while(preg_match($normreg, $path)) {
        $path = preg_replace($normreg, '$1', $path, 1);
    }

    [...]

    return $path;
}

我们跳过函数中不相关的部分,然后获取问题的核心,以及我们正在寻找的模式。我们看见事实上正则表达式习惯使用“normalize /../”。我们可以询问:你好,什么能导致错误?但是我们也知道了答案。

由于代码评论。我们知道模式被寻找到#(/)[^\/]+/\.\./# ,并且匹配到所有的都被一个“/.”替换,这个过程是被一直重复知道没有任何被匹配。

但是这个模式是错误的,这个//../序号永远不会被匹配,允许路径穿越到我们高亮的地方。

让我们启动IDE的go to refer转到引用功能,验证该函数是为文件行为调用链的部分。

  • Maj+F12: elFinderVolumeLocalFileSystem::_inpath
  • Maj+F12: elFinderVolumeLocalFileSystem::_stat
  • Maj+F12: elFinderVolumeDriver::stat
  • Maj+F12: WOWOWOW

elFinderVolumeDriver 调用第10个函数 stat 超过50次,包括一个调用file(我们调用API的行为名字)。大多数的这些函数都是控制器对于行为,这意味着我们的问题可能有一个更广阔的影响,在读取任意文件方面。

观察特征点

在我们参与的时候,发现已经足够获取RCE。我们的目标是运行Laravel示例,然后我们泄漏cookie值,你知道记过。

下一步的问题是:这个问题在目前最新的release中存在吗?现在的问题是从我们测试那个版本到最新的版本之间已经有50个小版本发布了。

$ git diff --ignore-cr-at-eol --ignore-space-at-eol -w --ignore-blank-lines 2.1.12 2.1.60 -- php/elFinderVolumeDriver.class.php
[...]
-       protected function getFullPath($path, $base) {
+    protected function getFullPath($path, $base)
+    {
        $separator = $this->separator;
        $systemroot = $this->systemRoot;
+        $base = (string)$base;

-               if ($base[0] === $separator && strpos($base, 0, strlen($systemroot)) !== $systemroot) {
+        if ($base[0] === $separator && substr($base, 0, strlen($systemroot)) !== $systemroot) {
            $base = $systemroot . substr($base, 1);
        }
+        if ($base !== $systemroot) {
+            $base = rtrim($base, $separator);
+        }

        // 'Here'
        if ($path === '' || $path === '.' . $separator) return $base;
@@ -5259,6 +6807,9 @@ abstract class elFinderVolumeDriver {
        while (preg_match($normreg, $path)) {
            $path = preg_replace($normreg, '$1', $path, 1);
        }
+        if ($path !== $systemroot) {
+            $path = rtrim($path, $separator);
+        }

使用diff工具在2.1.12和所谓的发布最新版本比较。没有发现在有漏洞的函数getFullPath函数有什么不同的改变。看起来似乎没有对应的补丁,但是在开香槟庆祝之前,我们要使用payload有效的攻击最新的版本验证漏洞是否攻击成功。

等等,我们发现了什么?

所以我们的漏洞函数并没有打补丁,可是我们的攻击payload没有起任何作用。当然,所以一定有另一个改变在软件中一定预防了直接的目录穿越。

由SonarSource[2]报告的漏洞中,有两个与路径遍历相关。elFinderVolumeLocalFileSystem_joinPath 方法是造成这个问题的根本原因。它在没有任何检查的情况下连接了两个路径,并使用下面的方式进行了修补:


_joinPath 函数的目录遍历补丁:

虽然该函数之前只是返回两个路径的连接,没有进一步的验证或清理,但新版本补丁包含了一些安全措施。特别是如果 _joinPath 函数是 file 操作的调用链的一部分,那么对 realpath 的调用可能会导致我们的问题。

  • 使用快捷键 Maj+F12 可以找到该函数的直接用法,包括几个与文件操作无关的控制器和 elFinderVolumeLocaleFileSystem::_abspath
  • 快捷键 Maj+F12 可以找到 elFinderVolumeDriver::abspathCE
  • 快捷键 Maj+F12 可以找到 elFinderVolumeDriver::decode
  • 几乎在所有地方都可以找到。

elFinderVolumeDriverdecode 方法实际上是用于解码 target 类型的参数(也就是从 l1_AAAA 参数中提取实际文件指针)。因此,在大多数action controllers中都会调用它,包括用于 file*调用的控制器,却无法绕过 decode 的调用。

但是,当我们我们追溯调用链到 _joinPath 并停在 elFinderVolumeLocaleFileSystem::_abspath,似乎并不总是会调用 _joinPath 函数。

protected function _abspath($path)
{
    if ($path === DIRECTORY_SEPARATOR) {
        return $this->root;
    } else {
        if (strpos($path, $this->systemRoot) === 0) {
            return $path;
        } else if (DIRECTORY_SEPARATOR !== '/' && preg_match('/^[a-zA-Z]:' . preg_quote(DIRECTORY_SEPARATOR, '/') . '/', $path)) {
            return $path;
        } else {
            return $this->_joinPath($this->root, $path);
        }
    }
}

事实上,只有在查询的路径是相对路径时才会调用_joinPath函数。但是在使用绝对路径直接返回了$path,所以应该足以在最新版本上利用此漏洞。

当然,仅仅将绝对路径(如/etc/passwd)直接传递给应用程序是肯定不能成功利用该漏洞的。

对于“路径是绝对路径时会发生什么”这个问题的答案实际上在调用getFullPath函数时的调用链中。如果回顾一下这个调用链,会发现其中经过一个名为_inpath的函数。这个函数可以防止路径遍历漏洞。

protected function _stat($path)
{
    $stat = array();

    if (!file_exists($path) && !is_link($path)) {
        return $stat;
    }

    //Verifies the given path is the root or is inside the root. Prevents directory traveral.
    if (!$this->_inpath($path, $this->root)) {
        return $stat;
    }

正如注释中所解释的那样,_inpath函数被用于验证请求的路径是否在配置的Web根目录内。即使我们知道这部分软件在处理点点斜杠时会出现问题,但是/etc/passwd不可能在root之内被考虑。所以要想实现这一点,提供的路径需要以配置的根路径作为前缀。

当然,这并非完全不可能。如果我们构建一个路径,确切地以该前缀开头,并利用双斜线技巧在它之后注入未经过滤的../字符序列,我们就应该能够通过所有的检查和防御函数。


漏洞成功利用!

如果您已经阅读到了这篇文章的这个部分,那么您可能已经知道,elFinder软件中存在一个路径遍历漏洞。其影响程度很大程度上取决于它所部署的上下文。至少可以进行任意文件读取,有时还足以实现远程代码执行。

正如我们之前所说,我们绕过的安全函数在多个action controllers中被使用。它应该能够调用像下面这样的动作:

  • search
  • upload
  • parents
  • subdirs

如果有合适的权限,这些功能就等同于读取、写入和浏览服务器的文件系统。

elFinder还有其他的控制防御机制,特别是文件扩展名的控制,可以防止写入任意的PHP脚本等。然而,这并不是在主机上执行代码所必需的。你只需替换authorized_keys文件、crontab文件,等等。

最后,利用这个问题的最新版本需要知道elFinder根目录的文件系统路径。这个路径可能会被猜测(如/var/www/html?/srv/php?),通过暴力破解或通过另一个漏洞泄露,这部分留给读者自己去练习了。

在2.1.59之前的所有版本中并非都需要这样做。但在那些版本中,您可能也可以利用Sonar的Thomas报告的RCE漏洞。有可能您跟我们一样幸运...

Date Action
2022-03-08 漏洞提交
2022-03-09 修补程序
2022-03-14 CVE-2022-26960 发布
2022-03-14 elFinder 2.1.61 修复版本发布

CVE-2022-26960是关于elFinder的一个安全漏洞,该漏洞可能会被攻击者利用进行路径遍历并读取、写入、浏览配置文件根目录外的文件。

[1] elFinder命令注入 < 2.1.48 https://www.synacktiv.com/ressources/advisories/elFinder_2.1.47_Command_Injection.pdf

[2] elFinder -Web文件管理器漏洞案例的研究 https://blog.sonarsource.com/elfinder-case-study-of-web-file-manager-vulnerabilities


文章来源: https://xz.aliyun.com/t/12447
如有侵权请联系:admin#unsafe.sh