0x00 前言
在本文中,我将与大家分享Seagate Central Storage NAS产品中存在的一些严重漏洞。
漏洞概要信息如下:
远程利用:是
需要认证:否
厂商URL:https://www.seagate.com/as/en/support/external-hard-drives/network-storage/seagate-central/
发现时间:2019年12月19日
0x01 技术细节
从Seagate官方下载页面下载最新版设备固件后,我开始ZIP固件包。ZIP文件中包含经过压缩的一个二进制文件:Seagate-HS-update-201509160008F.img
,简单将该文件扩展名改为tar.gz
后,我们可以成功提取出其中的SquashFS文件系统。该文件系统中包含适用于ARM架构NAS设备的管理应用程序的源代码、启动脚本以及busybox文件。
图1. 固件更新ZIP包中的内容
使用sudo unsquashfs -f -d /media/seagate /tmp/file.squashfs
命令挂载文件系统后,我开始分析其中包含的内容。经过简单探索后,我找到了设备管理接口对应的PHP源代码,因此可以直接转入源代码分析阶段。在分析过程中,我发现应用程序使用CodeIgniter框架开发。由于管理应用本身较为庞大,因此我重点关注的是可能存在漏洞的PHP函数。使用find . -name "*.php" | xargs grep "<function-name>"
命令后,我们可以得到如下函数列表,找到比较有趣的一些输入点:
exec
shell_exec
system
passthru
pcntl_exec
popen
proc_open
eval
preg_replace (带有 /e 修饰符)
create_function
file_get_contents
file_put_contents
readfile
include
require
require_once
include_once
通过grep
命令查找proc_open
关键字后,我们在./cirrus/application/helpers/mv_backend_helper.php
文件中找到了1处调用,该调用以多个动态变量作为参数。
具体代码如下:
function mv_backend_launch($cmd, $noLog = false)
{
$desc = array(
0 => array("pipe","r"),
1 => array("pipe","w"),
2 => array("pipe","w")
);
$cwd = './';
$process = proc_open($cmd,$desc,$pipes,$cwd);
if(is_resource($process))
{
fclose($pipes[0]);
$data =stream_get_contents($pipes[1]);
fclose($pipes[1]);
$errors=stream_get_contents($pipes[2]);
if(strlen(trim($errors))>0)
mv_log_errors($cmd,$errors);
fclose($pipes[2]);
proc_close($process);
if ( ! $noLog ) {
syslog(LOG_INFO, "CMD: '$cmd', RESPONSE: '$data'");
}
return $data;
}
}
追溯函数引用后,我找到了一个函数:check_device_name
,该函数会将未经过滤的用户输入通过$name
参数传递给mv_backend_launch
函数。
public function check_device_name()
{
$info = $this->get_start_info();
$isStart = $info && array_key_exists('state', $info) && $info['state'] == 'start';
if ( ! $isStart ) {
mv_is_admin();
}
$name = $this->input->post("name");
$result = mv_backend_launch("check_netbios_name.sh $name");
echo header('Content-type: text/xml');
echo $result;
}
因此在这里我们找到了一个有趣的函数,并且该函数存在远程代码执行漏洞。但这里的问题在于,只有当设备状态设置为start
时,该函数才有效,否则我们需要具备admin
级别的访问权限才能触发该漏洞。因此我们需要找到无需身份认证就能修改设备状态的方法,或者需要进一步绕过身份身份认证,实现权限提升。为了解决该问题,我重新分析源代码,最终找到了一个更为优秀的攻击点。在分析设备状态机制时,我注意到当处于start
状态时,设备会允许新用户注册操作,以便执行设备初始化设置。当我继续研究修改设备状态的具体逻辑时,我找到了application/core/MV_BaseController.php
文件中的set_start_info
函数。该函数可以通过JSON POST请求来设置设备状态,并且最为关键的是,整个过程没有任何访问控制机制!
public function reset_start_info()
{
self::save_object_to_file(null, self::START_FILE);
$uri = $_SERVER['REQUEST_URI'];
$idx = strpos($uri, 'index.php');
if ( $idx !== false ) {
$uri = substr($uri, 0, $idx);
}
$uri .= 'index.php/SCSS';
header('Content-type: text/plain');
header("Location: ".$uri, TRUE, 302);
exit();
}
因此,我们可以直接将设备状态修改为start
,然后就能添加一个新的admin
用户。设备所属的用户同样对应于Linux系统用户,因此这些用户都具备该设备的SSH访问权限。
0x02 Metasploit模块
此时我们已经找到了多个漏洞。在漏洞利用方式上我更喜欢使用第二种方法,通过添加新的admin
用户来建立SSH连接。考虑到Metasploit payload的兼容性,使用busybox程序来触发反向/bind shell连接是比较艰巨的一个任务。此外,除了HTTP、HTTPS、SSH、FTP等端口外,其他端口默认处于关闭状态。由于SSH默认处于启用状态,并且用户无法通过管理员接口禁用该功能,因此第二种利用方式显然更为方便。
最终利用效果可参考此处视频。
0x03 厂商反馈
向Seagate反馈该漏洞后,对方给了我们不小的打击。Seagate一开始声称“该产品主要面向个人家庭,针对个人局域网使用”,因此实际上并不存在可用的攻击面。随后我们通过shodan.io以及censys.io找到了向互联网开放的一些目标设备,但似乎对方并不关心这个事实。既然我们不期望能拿到任何漏洞奖励或者积分,我们只能将研究成果公之于众。我们与厂商的讨论过程如下所示,之所以选择Bugcrowd平台,是因为Seagate只接收通过外部Bugcrowd表单提交的bug报告。
发表评论
您还未登录,请先登录。
登录