西部数码MyCloud NAS命令执行漏洞
在这篇文章中,我将要解释我是如何发现西部数据NAS设备的一些漏洞的,组合在一起后最终可以实现root权限的远程代码执行的效果。
要想控制NAS设备,需要保证攻击者与NAS设备处于同一网络,并且知道其真实IP。
前奏
这一切均源于,我决定斥资购买西部数据(WD)My Cloud EX2 Ultra
。与其他型号不同,这款产品为消费者提供了切换硬盘驱动器的功能,可以让你无需额外安装应用程序即可使用它,甚至还可以在没有互联网的情况下使用。
在安装这个设备时,我决定先打开浏览器测试一下,幸不辱命,发现一个绕过身份验证的方法(通过设置cookie中的“isAdmin”为1)。奈何,在更新NAS以后,我发现这个漏洞已经在新版本中修复了。
此时我觉得肯定还会有其他漏洞,于是我决定继续测试下去。当我下载了WD网站的源代码以后,便开始搜索刚才这处校验用户身份的代码,终于成功找到我想要的代码片段。我发现更新后的代码中已经不再是依赖用户的Cookie信息,而是改为校验Session。
/* fixed code in
firmware/module/crfs/web/pages/lib/login_checker.php
*/
function login_check()
{
$ret = 0;
if (!csrf_token_check()) /* this check can be bypassed easily as well */
return $ret;
if (isset($_SESSION['username']))
{
if (isset($_SESSION['username']) && $_SESSION['username'] != "")
$ret = 2; //login, normal user
if ($_SESSION['isAdmin'] == 1)
$ret = 1; //login, admin
}
return $ret;
}
未经校验的文件上传漏洞(CVE–2019-9951)
通过审计这些“可爱的”PHP代码,我发现有一处没有正确使用login_check函数,从而导致未经校验的文件上传漏洞。
/* found in:
firmware/module/crfs/web/pages/jquery/uploader/uploadify.php
*/
include ("../../lib/login_checker.php");
if (login_check() != 1) /* i.e not-authenticated / admin */
{
/* user-controlled */
if ($_SERVER['HTTP_USER_AGENT'] == 'Shockwave Flash')
{
$headers = getallheaders();
/* also user-controlled */
if ($_GET['WD-CSRF-TOKEN'] !== $_POST['X-CSRF-Token'] ||
strrpos($headers['Content-Type'], 'multipart/form-data;'))
{
echo json_encode($r);
exit;
}
/* >> by reaching this line, you bypassed the authentication for this page*/
}
else
{
echo json_encode($r);
exit;
}
}
/* upload logic here */
不过,这还无法直接利用。因为uploadify.php文件将会校验目的路径并且限制仅允许写入到特定目录。
/* found in:
firmware/module/crfs/web/pages/lib/login_checker.php
*/
function check_path($path)
{
$file_path = realpath($path);
if (!$file_path) return false;
if (strncmp($file_path, "/mnt/HD", 7) != 0 &&
strncmp($file_path, "/mnt/USB", 8) != 0 &&
strncmp($file_path, "/mnt/isoMount", 13) != 0)
return false;
return true;
}
身份认证绕过(CVE-2019-9950)
证书在cgiMain导出的函数firmware/module/crfs/cgi/login_mgr.cgi中被管理。
事实证明,控制面板利用内置的操作系统凭证管理。这允许控制面板对照/etc/shadow中存储的用户名和密码检查提供的用户名和密码:
在如上文件中查找 nobody账户的密码,这个密码使用了旧的CRYPT算法加密:
nobody:pACwI1fCXYNw6:0:0:99999:7:::
我们可以使用John the Ripper
或者 hashcat
来尝试破解这个hash,但是我觉得下面这种表示方式或许更加直观。
更搞笑的是,NAS中的用户名默认密码为空,因此任何人都可以轻而易举的获取一个session token。
POST http://WD/cgi-bin/login_mgr.cgi
{
"cmd": "wd_login",
"username": "nobody",
"pwd": "",
"port": "",
}
使用低权限获取root权限的RCE(CVE-2019-9949)
当我们拥有了一个标准的权限token时,我们将有权获取并访问更多的攻击面。里面有一个文件管理功能(主要由webfile_mgr.cgi文件控制),但是有些功能被限制了,不支持打开zip/tar格式的文档。
当点击上图中的按钮时,将会发送如下带有cgi_unzip命令的HTTP请求到webfile_mgr.cgi文件。
Request URL: "http://wd/cgi-bin/webfile_mgr.cgi"
Request method: "POST"
cmd: "cgi_unzip"
path: "/mnt/HD/HD_a2/Public/test"
name: "myfile.zip"
之后,在firmware/module/crfs/web/pages/cgi_api.php文件中通过必要的路由和权限的校验后,cgi模块会通过转义路径来强制校验输入,然后再执行带有-t选项的unzip命令。
/* ... in webfile_mgr.cgi */
fix_path_special_char_inline(archive_name); // user controlled
// target_dir is checked to exist in the PHP code
sprintf(cmdline, "cd %s;/usr/bin/unzip -t %s", target_dir, archive_name);
ret = popen(cmdline, "r");
/* ... */
跟进fix_path_special_char_inline函数,可以看到校验很松散:
def fix_path_special_char_inline(input_str):
out_str = ''
for c in input_str:
if c in '`$#%^&()+{};[]\=': # much secure
out_str += '\\'
out_str += c
return out_str
可以看到使用了黑名单校验,在这个黑名单中,并没有校验管道符(|)。在bash或batch的世界中,当双管道符(||)处于两个命令之间时,前面的命令执行失败了,那么便会继续执行后面的命令。
在这种情境下,通过使前面unzip命令执行失败,攻击者可以注入一个root权限运行的shell命令。例如:
cd %s;/usr/bin/unzip -t 1||%MY_EVIL_COMMAND%
再来一个
事实证明,这里的文件管理功能很容易受到其他攻击。具体来说,使用符号链接提取存档将不需要进一步验证就可以创建它们,从而允许将来的文件系统操作滥用它们而不做任何限制。
例如:如果两个连续的cgi_untar命令在两份精心构造的存档上被执行时,可以导致任意文件写入漏洞(root权限)。同样,这个漏洞也仅需要一个普通用户权限。
发生这种情况的原因是,在提取压缩文件的代码中将使用cig_untar命令进行简单的解压缩操作,即使目标包含符号链接。然后,在提取第二个压缩文件时,攻击者可以使用事先构造好的符号链接写入到任意路径。
因为NAS使用的是squashfs,因此不是所有的路径都是可写的,例如,/bin/目录便不可以。为了娱乐最大化,我决定覆盖tar自己本身,因此可以通过如下操作来实现RCE:
上传第一个压缩文档,其中包含符号链接
发送cgi_untar命令:创建指向/bin/目录的符号链接
上传第二个压缩文档,其中包含Payload
发送cig_untar命令:覆盖/bin/tar文件
发送cig_untar命令:执行我的Payload
我觉得第二个漏洞尽管很严重,但是却不值得拥有一个属于自己的CVE编号。
漏洞时间轴
2019-01-20 向psirt@wdc.com发送报告并遵守30天的披露期限
2019-01-22 WD发送了自动回复
2019-02-05 被要求确认问题
2019-02-06 WD要求90天内解决问题
2019-03-05 请求的状态更新
2019-03-15 WD要求额外延长90天
2019-03-16 同意延长30天
2019-03-27 WD发布第一个补丁(CVE-2019-9950,CVE-2019-9951)
2019-05-20 WD 发布第二个补丁(CVE-2019-9949)
2019-05-22 公开漏洞
1. My Cloud EX2 Ultra测试所有版本号:2.31.149_20181015
2. 不过我当时并不知道在exploiteers已经被公布过
3. https://community.wd.com/t/new-release-my-cloud-firmware-versions-2-31-174-3-26-19/235932
4. https://community.wd.com/t/new-release-my-cloud-firmware-versions-2-31-183-05-20-2019/237717
本文由白帽汇整理并翻译,不代表白帽汇任何观点和立场
来源:https://bnbdr.github.io/posts/wd/
最新评论