
在Exploitee.rs,我们有时会寻找有趣的设备进行安全研究,有时设备会主动引起我们的注意。今天我们将讨论最近遇到的后一种情况,以及我们在西部数据系列网络附加存储(NAS)设备上的研究经验。
去年年中,我(Zenofex)开始寻找一款能通过我当前偏好的媒体播放器Plex提供硬件解码的NAS设备。经过一番研究,我订购了西部数据"MyCloud" PR4100。该设备满足了我的所有要求,并受到朋友的高度推荐。将NAS添加到网络并首次访问设备的管理页面后,我开始担心在没有进行适当审计的情况下将新设备添加到网络中。因此,我登录设备,启用SSH访问,并查看了设备的Web服务器功能工作原理。
我很快发现了第一个让我震惊的漏洞,这个漏洞基于执行用户登录检查但使用cookie或PHP会话变量的代码。使用cookie进行身份验证本身不一定有问题,但西部数据MyCloud界面使用它们的方式存在问题。
/lib/login_checker.php
function login_check()
{
$ret = 0;
if (isset($_SESSION['username']))
{
if (isset($_SESSION['username']) && $_SESSION['username'] != "")
$ret = 2; //普通用户登录
if ($_SESSION['isAdmin'] == 1)
$ret = 1; //管理员登录
}
else if (isset($_COOKIE['username']))
{
if (isset($_COOKIE['username']) && $_COOKIE['username'] != "")
$ret = 2; //普通用户登录
if ($_COOKIE['isAdmin'] == 1)
$ret = 1; //管理员登录
}
return $ret;
}上述代码包含一个名为"login_check"的函数,该函数被所有后端PHP脚本使用,用于验证预认证用户。代码有两条路径:一条检查会话值"username"和"isAdmin",另一条(如果前者失败)尝试使用cookie完成相同过程。由于cookie由用户提供,攻击者可以满足脚本寻找的要求。
在编写研究结果的过程中,推出了新的固件修补了上述漏洞。然而,这个补丁引入了一个新的漏洞,其后果与原始漏洞相同。
/var/www/web/lib/login_checker.php
20 function login_check()
21 {
22 $ret = 0;
23
24 if (isset($_SESSION['username']))
25 {
26 if (isset($_SESSION['username']) && $_SESSION['username'] != "")
27 $ret = 2; //普通用户登录
28
29 if ($_SESSION['isAdmin'] == 1)
30 $ret = 1; //管理员登录
31 }
32 else if (isset($_COOKIE['username']))
33 {
34 if (isset($_COOKIE['username']) && $_COOKIE['username'] != "")
35 $ret = 2; //普通用户登录
36
37 if ($_COOKIE['isAdmin'] == 1)
38 $ret = 1; //管理员登录
39
40 if (wto_check($_COOKIE['username']) === 0) //wto检查失败
41 $ret = 0;
42 }
43
44 return $ret;
45 }
46 ?>在更新版本的代码中,调用了新方法"wto_check()"(第40行)。该函数在设备上运行一个二进制文件,使用客户端提供的用户名和用户的IP地址作为参数。
/var/www/web/lib/login_checker.php
3 /*
4 返回值: 1: 已登录, 0: 未登录
5 */
6 function wto_check($username)
7 {
8 if (empty($username))
9 return 0;
10
11 exec(sprintf("wto -n \"%s\" -i '%s' -c", escapeshellcmd($username), $_SERVER["REMOTE_ADDR"]), $login_status);
12 if ($login_status[0] === "WTO CHECK OK")
13 return 1;
14 else
15 return 0;
16 }
17
18 /* ret: 0: 未登录, 1: 管理员登录, 2: 普通用户登录 */
19 在第11行,命令被格式化为包含用户名和IP地址作为"wto"二进制文件的参数。问题在于错误使用了PHP方法"escapeshellcmd()",该方法旨在处理整个命令字符串,而不是单个参数。这是因为"escapeshellcmd()"函数不转义引号,因此允许攻击者突破封装引号(在我们的例子中是"-n"参数),允许向二进制文件提供新参数。
WDCloud Web界面的大部分功能实际上由设备上的CGI脚本处理。大多数二进制文件使用相同的模式:它们从请求中获取post/get/cookie值,然后在PHP调用中使用这些值来执行shell命令。在大多数情况下,这些命令使用用户提供的数据,很少或没有进行清理。
php/users.php
15 $username = $_COOKIE['username'];
16 exec("wto -n \"$username\" -g", $ret);上面的代码将来自COOKIE超全局变量的值分配给局部变量"$username",然后立即在PHP"exec()"调用中用作本地"wto"二进制文件的参数。由于没有清理,使用像username=$(touch /tmp/1)这样的用户名值会将现有的exec命令转换为wto -n "$(touch /tmp/1)" -g,并在其中执行用户提供的命令。
这种导致命令注入漏洞的基本模式在Web界面使用的许多脚本中多次使用。虽然有些可能通常通过需要身份验证来防止,但上述身份验证绕过克服了该限制。此外,重要的是要注意,通过Web界面执行的所有命令都是以Web服务器运行的用户身份执行的,在这种情况下是root。
虽然您可能认为上述漏洞很严重,但Web界面中还有许多其他错误,有些就像普通身份验证被注释掉一样简单:
addons/ftp_download.php
6 //include ("../lib/login_checker.php");
7 //
8 ///* login_check() return 0: no login, 1: login, admin, 2: login, normal user */
9 //if (login_check() == 0)
10 //{
11 // echo json_encode($r);
12 // exit;
13 //}还有其他更具体的功能问题,如以下示例中的漏洞允许未经身份验证的用户将文件上传到myCloud设备。
addons/upload.php
2 //if(!isset($_REQUEST['name'])) throw new Exception('Name required');
3 //if(!preg_match('/^[-a-z0-9_][-a-z0-9_.]*$/i', $_REQUEST['name'])) throw new Exception('Name error');
4 //
5 //if(!isset($_REQUEST['index'])) throw new Exception('Index required');
6 //if(!preg_match('/^[0-9]+$/', $_REQUEST['index'])) throw new Exception('Index error');
7 //
8 //if(!isset($_FILES['file'])) throw new Exception('Upload required');
9 //if($_FILES['file']['error'] != 0) throw new Exception('Upload error');
10
11 $path = str_replace('//','/',$_REQUEST['folder']);
12 $filename = str_replace('\\','',$_REQUEST['name']);
13 $target = $path . $filename . '-' . $_REQUEST['index'];
14
15 //$target = $_REQUEST['folder'] . $_REQUEST['name'] . '-' . $_REQUEST['index'];
16
17 move_uploaded_file($_FILES['file']['tmp_name'], $target);
18
19
20 //$handle = fopen("/tmp/debug.txt", "w+");
21 //fwrite($handle, $_FILES['file']['tmp_name']);
22 //fwrite($handle, "\n");
23 //fwrite($handle, $target);
24 //fclose($handle);
25
26 // 可能执行太快
27 sleep(1);上述代码不包含身份验证检查,调用时只会检索上传的文件内容并使用用户提供的路径来确定新文件的放置位置。
大部分(如果不是全部)研究结果可以应用于整个西部数据MyCloud产品系列,包括以下设备:
在Exploitee.rs,我们通常尝试与供应商合作,确保漏洞得到适当修复。然而,在参加了上次BlackHat Vegas的Pwnie Awards后,我们了解了该供应商在社区中的声誉。特别是,该供应商在忽视向他们报告的一组漏洞的严重性的情况下赢得了"最差供应商响应Pwnie奖"。忽视这些漏洞将使易受攻击的设备在负责任披露过程中在线时间更长。相反,我们试图提醒社区注意这些缺陷,并希望用户将其设备从网络的任何公共部分移除,尽可能限制访问。通过这个过程,我们完全披露了所有研究结果,并希望这能加速用户设备的补丁发布。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。