专栏名称: 看雪学苑
致力于移动与安全研究的开发者社区,看雪学院(kanxue.com)官方微信公众帐号。
目录
相关文章推荐
偶俚张家港  ·  蔚来:已报警! ·  21 小时前  
偶俚张家港  ·  蔚来:已报警! ·  21 小时前  
重庆日报  ·  小猿搜题等82款违法违规App被查处 ·  昨天  
重庆日报  ·  小猿搜题等82款违法违规App被查处 ·  昨天  
昆明警方发布  ·  警惕!传播“病毒”的新手法出现 ·  昨天  
昆明警方发布  ·  警惕!传播“病毒”的新手法出现 ·  昨天  
安全学习那些事儿  ·  国家公共数据资源登记平台将于3月上线 ·  2 天前  
安全学习那些事儿  ·  国家公共数据资源登记平台将于3月上线 ·  2 天前  
python自留地  ·  2月5日,奇安信安全智能体深度接入DeepS ... ·  3 天前  
python自留地  ·  2月5日,奇安信安全智能体深度接入DeepS ... ·  3 天前  
51好读  ›  专栏  ›  看雪学苑

攻击 Western Digital NAS 个人云存储设备

看雪学苑  · 公众号  · 互联网安全  · 2017-03-18 18:02

正文

在 Exploitee.rs,有时我们寻找有趣的设备进行攻击,而有时设备会找到我们。今天,我们将谈谈最近一段时间(我们发现自己处于后一种情况)我们在攻击一系列 Western Digital 的网络附加存储设备方面的经验。

去年年中,我开始寻找一个能借助 Plex(一款我最近很喜欢用的媒体播放器)提供硬件解码功能的网络附加存储设备。经过一番研究,我订购了一个 Western Digital“MyCloud”PR4100。这个设备满足了我的所有需求,并得到一个朋友强烈推荐。在将 NAS 添加到我的网络并首次访问设备的管理页面之后,我对在网络中不经适当审核而添加新设备感到厌烦。所以,我登录该设备,启用 SSH 访问,并查看该设备的 Web 服务器功能如何工作。

💎 登录绕过

我很快发现第一个令人震惊的 bug,这个 bug 来自于一段执行用户登录检查功能(使用 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; //login, normal user

if ($_SESSION['isAdmin'] == 1)

$ret = 1; //login, admin

}

else if (isset($_COOKIE['username']))

{

if (isset($_COOKIE['username']) && $_COOKIE['username'] != "")

$ret = 2; //login, normal user

if ($_COOKIE['isAdmin'] == 1)

$ret = 1; //login, admin

}

return $ret;

}

上述代码包含一个名为“login_check”的函数,此函数由所有后端 PHP 脚本使用,用于验证预认证的用户。上面的代码可以通过两条途径完成检查,第一是通过检查“username”和“isAdmin”的会话值,第二是(如果先前失败)尝试使用 cookie 完成相同的过程。因为 cookie 是由用户提供的,所以脚本寻找的要求可以被攻击者满足。上述会话和 cookie 的检查过程总结如下。

  • “username”变量已设置,并且不为空 - 用户以普通权限用户身份登录。

  • “isAdmin”变量设置为1 - 用户以管理员身份登录。

这意味着在任何时候使用该 PHP 脚本进行登录检查时,攻击者能够通过提供 2个特制的 cookie 值绕过检查。

在写下我发现的过程中,一个新的固件被推出来修补上述 bug。然而,这个补丁引入了一个新的漏洞,它具有与上述 bug(更新前)相同的后果。下面是包括固定代码的当前版本。

/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; //login, normal user

28

29                 if ($_SESSION['isAdmin'] == 1)

30                         $ret = 1; //login, admin

31         }

32         else if (isset($_COOKIE['username']))

33         {

34                 if (isset($_COOKIE['username']) && $_COOKIE['username'] != "")

35                 $ret = 2; //login, normal user

36

37                 if ($_COOKIE['isAdmin'] == 1)

38                         $ret = 1; //login, admin

39

40                 if (wto_check($_COOKIE['username']) === 0) //wto check fail

41                         $ret = 0;

42         }

43

44         return $ret;

45 }

46 ?>

在代码的更新版本中,调用了新函数“wto_check()”(40行)。此函数使用客户端提供的用户名以及用户的 IP 地址作为二进制参数在设备上运行。如果用户当前已经登录并且没有超时,则返回值 1,否则返回 0(指示用户未登录)。“wto_check()”方法的代码如下。

/var/www/web/lib/login_checker.php

3 /*

4   return value: 1: Login, 0: No login

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: no login, 1: login, admin, 2: login, normal user */

19

在上面的代码中你可以看到,为了将用户名和 IP 地址引入作为“wto”二进制的参数,在第 11 行进行了转义处理。上面代码的问题是 PHP 方法“escapeshellcmd()”的不正确使用,“escapeshellcmd()”的正确用途是处理整个命令字符串,而不仅仅是一个参数。这是因为“escapeshellcmd()”函数不转义引号,因此攻击者可以突破引号的封装(在我们的案例中为“-n”参数),允许引入新的参数执行。因此,我们可以添加新的参数实现自我登录,而绕过对用户是否已经登录的检查。尽管我们认为仅仅通过检查IP地址和是否登录超时来验证用户是否已经登录是远远不够的。编写这段代码的程序员应该使用“escapeshellarg()”,它用于过滤独立的二进制参数,并过滤掉引号。使用“escapeshellarg()”而不是目前使用的“escapeshellcmd()”至少可阻止上述提到的攻击。

💎 命令注入错误

WDCloud Web 界面的大多数功能实际上由设备上的 CGI 脚本处理。大多数二进制文件使用相同的模式,它们从请求中获取 post / get / cookie 值,然后使用 PHP 调用中的值来执行shell命令。在大多数情况下,这些命令将使用用户提供的数据(几乎不进行清理)。例如,考虑一下以下代码(来自于该设备)。

php/users.php

15 $username = $_COOKIE['username'];

16 exec("wto -n \"$username\" -g", $ret);

上面的代码从 COOKIE 的超全局变量(包含从请求提交来的 cookie 数组索引)分配一个值给本地变量“$ username”。然后,该值作为本地方法“wto”的二进制参数立即在 PHP 的“ exec() ”调用中被使用。因为没有数据清理,使用用户名值

username=$(touch /tmp/1)

将现有的 exec 命令转换为

wto -n "$(touch /tmp/1)" -g

并在其中执行用户提供的命令。

因为参数用双引号封装且我们使用“$(COMMANDHERE)”这样的语法,命令“touch / tmp / 1”先于“wto”方法被执行,其返回值被用作“wto”方法的“-n”参数。这种导致命令注入漏洞的基本模式在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 // Might execute too quickly.

27 sleep(1);

上面的代码由未经检查的身份验证组成,该段代码被调用时将简单地检索上传的文件内容,并根据用户提供的路径来决定在哪里放置新文件。

除了本博客中列出的错误,我们将在 MyCloud Web 界面中发现的大量错误放在我们的 wiki 中。尽快修复错误是我们 Exploitee.rs 的普遍追求。然而,大量的严重错误的发现意味着,我们可能需要在供应商正确修复已发布的漏洞后重新评估产品。

💎 责任披露

Exploitee.rs 通常致力于同供应商合作,确保漏洞被正确地发布。然而,上一次在维加斯的 BlackHat 大会上取得了 Pwnie奖 后,我们了解了供应商在圈子里的声誉。特别地,某供应商在忽略了向他们所提交的一组错误的严重性后,仍然赢得了“Lamest Vendor Response” Pwnie奖。厂商的忽略使得易受攻击的设备更长时间地在线(尽管已经做过了责任披露)。因此,我们转而尝试向圈内人士做出有关这些缺陷的预警,并希望用户将其设备从接入公网的网络中转移走,或是尽可能限制访问。通过这个过程,我们完全公开了我们的所有研究,并希望这会加快给用户设备打补丁的速度。

找到的 Bug 统计信息

  • 1 x绕过登录

  • 1 x任意文件写入

  • 13 x未经身份验证的远程命令执行Bug

  • 70 x需要验证命令执行Bug*

*绕过登录Bug 可以取得和“需要验证”Bug一样的效果。

💎 范围

即便不是全部也可以说是大多数,本项研究可以应用于西部数据的整个 MyCloud 系列产品。包括以下设备:

  • My Cloud

  • My Cloud Gen 2

  • My Cloud Mirror

  • My Cloud PR2100

  • My Cloud PR4100

  • My Cloud EX2 Ultra

  • My Cloud EX2

  • My Cloud EX4

  • My Cloud EX2100







请到「今天看啥」查看全文


推荐文章
偶俚张家港  ·  蔚来:已报警!
21 小时前
偶俚张家港  ·  蔚来:已报警!
21 小时前
昆明警方发布  ·  警惕!传播“病毒”的新手法出现
昨天
昆明警方发布  ·  警惕!传播“病毒”的新手法出现
昨天
安全学习那些事儿  ·  国家公共数据资源登记平台将于3月上线
2 天前
安全学习那些事儿  ·  国家公共数据资源登记平台将于3月上线
2 天前
朱莉生活日记  ·  除了青团子,清明节还有这些美味!
7 年前
印象笔记  ·  你是如何一步步失去自我的?
7 年前