|
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 中进行了修补,但我们看到一些人设法扭转了补丁并利用了一些服务器。
所以重申一下步骤:
编辑:航网科技 来源:腾讯云 本文版权归原作者所有 转载请注明出处
微信扫一扫咨询客服
全国免费服务热线
0755-36300002