Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >专栏 >如何用0day漏洞黑掉西部数据NAS存储设备

如何用0day漏洞黑掉西部数据NAS存储设备

作者头像
FB客服
发布于 2018-02-23 08:55:52
发布于 2018-02-23 08:55:52
1.5K0
举报
文章被收录于专栏:FreeBufFreeBuf

我们以入侵和破解设备为乐,今天,要向大家展示的是近期我们对西部数据(Western Digital )网络存储设备(NAS)的漏洞发现和入侵利用过程。点击阅读原文观看入侵视频。

漏洞发现

去年年中,我打算入手一台支持硬件解码的NAS存储来搭建Plex流媒体服务平台,经过一番比较,在一位朋友的推荐下,我选择了西部数据(Western Digital )的MyCloud PR4100,该存储设备完全满足我所有的功能需求。把该设备添加进网络之后,可以通过一个Web界面访问登录,由于我对使用设备有安全洁癖,所以在登录开启SSH连接之后,我开始对其网页服务功能进行了安全审计,并发现了以下存在漏洞:

登录验证绕过漏洞

很惊讶,我很快发现了一个用cookie和PHP session进行登录检查的bug。虽然使用cookie认证并不都是坏事,但该设备的使用方式存在问题,请看以下脚本:

/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, normaluser if ($_COOKIE['isAdmin'] == 1) $ret = 1; //login,admin } return $ret; }

代码包含一个名为 “login_check”的函数,后台PHP脚本通过调用该函数对预登录用户进行认证校验。函数代码显示,可以通过两种方式进行认证,一种是session方式的“username”“isAdmin”判断,另一种是cookie方式的判断。由于cookie由用户执行产生,所以攻击者同样可以构造满足脚本调用的恶意请求。上述代码认证方式可以归纳为以下方式:

当存在“username” 变量且不为空时,用户作为正常权限用户登录; 当存在“isAdmin”变量且不为空时,用户作为管理员登录;

这意味着,只要使用php脚本进行登录验证时,攻击者就可以构造特殊cookie变量绕过验证。

补丁更新导致新的漏洞

然而,就在我的研究过程中,该存储设备的一个固件更新释出对上述bug的修复补丁。但更不可思议的是,该补丁却导致了另外一种方式的验证绕过漏洞。以下是更新后的登录验证脚本:

/var/www/web/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 if(wto_check($_COOKIE['username']) === 0) //wto check fail $ret = 0; } return $ret; } ?>

更新后的代码第40行,增加了对用户验证的 “wto_check()”方法,用户名和IP地址都是该方法的参数。当前登入用户保持操作状态,则返回1,超时则返回0。“wto_check()”实现代码如下:

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

/* return value: 1: Login, 0: No login */ function wto_check($username) { if (empty($username)) return 0; exec(sprintf("wto -n \"%s\" -i '%s' -c",escapeshellcmd($username), $_SERVER["REMOTE_ADDR"]), $login_status); if ($login_status[0] === "WTO CHECK OK") return 1; else return 0; } /*ret: 0: no login, 1: login, admin, 2: login, normal user */

上述代码第11行中,用户名和IP地址被初始化为wto变量参数,而问题就出在用来处理整个命令字符串的方法“escapeshellcmd()”,该方法不会对-n参数中配对的引号进行转义,这就给了攻击者重新构造或绕过验证的可能,因此,我们可以添加新的参数绕过验证并执行任意用户登录。

Freebuf百科:escapeshellcmd()对字符串中可能会欺骗shell命令执行任意命令的字符进行转义。 此函数保证用户输入的数据在传送到 exec()或 system()函数,或者执行操作符之前进行转义。反斜线(\)会在以下字符之前插入: #&;`|*?~<>^()[]{}$\, \x0A 和 \xFF。 而' 和 " 仅在不配对的时候被转义,在 Windows 平台上,所有这些字符以及 % 都会被前缀 ^ 来转义。(详细请参考 php.net相关说明)

这里,最好使用Escapeshellarg方法函数,Escapeshellarg()会将任何引起参数或命令结束的字符进行转义,如单引号“’”会被转义为“\’”,双引号“””会被转义为“\””,分号“;”会被转义为“\;”,这样escapeshellarg会将参数内容限制在一对单引号或双引号里面,转义参数中所包含的单引号或双引号,使其无法对当前执行进行截断,实现防范命令绕过或注入攻击的目的。

命令注入漏洞

大多数的西部数据MyCloud设备Web界面,实际上是由CGI脚本来实现的,这些脚本中大部分二进制文件都存在着相同的功能模式,如从请求包中获取post/get/cookie值,然后应用这些值执行相关命令。然而,大多数情况下,这些命令会使用到用户提交的一些未经安全处理的恶意数据。例如,以下设备中存在的代码:

php/users.php

15 $username = $_COOKIE['username']; 16 exec("wto -n\"$username\" -g", $ret);

代码把包含cookie值的全局变量数组$_COOKIE命名为”$username”,之后,该”$username”作为后续“exec()”命令执行的调用参数。因为没有任何过滤措施,可以这样更改一下,把username值设为:

username=$(touch /tmp/1)

那么执行命令将会变为:

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

很容易就执行了用户的自定义命令。

由于命令行参数被双引号封装,在执行“$(COMMANDHERE)”语法时,命令“touch /tmp/1”先于wto前就已经执行,并把返回结果作为-n参数。这种web接口对内置脚本的交互调用模式,明显会导致命令注入漏洞。而且,使得注意的是,所有通过web端构造的命令都会被以root权限执行。

其它Bug

除了以上两个高危漏洞之外,该设备在web服务方面还存在其它一些严重Bugs,比如以下文件中正常登录验证行为被错误地注释掉:

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//}

而以下上传功能文件可以针对设备系统,执行无需用户验证的,任意目录位置的任意文件上传:

addons/upload.php

2 //if(!isset($_REQUEST['name'])) throw newException('Name required'); 3//if(!preg_match('/^[-a-z0-9_][-a-z0-9_.]*$/i', $_REQUEST['name'])) throw newException('Name error'); 4// 5//if(!isset($_REQUEST['index'])) throw new Exception('Index required'); 6//if(!preg_match('/^[0-9]+$/', $_REQUEST['index'])) throw new Exception('Indexerror'); 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 17move_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. 27sleep(1);

除此之外,我们还发现了另外一个个远程命令执行漏洞(RCE)和身份验证命令执行漏洞,在此就不作公开。由于这些漏洞在此之前,没人发现或爆料过,可以算是西部数据NAS设备的0day漏洞。

漏洞总结

1 x 登录验证绕过漏洞 1 x 任意文件上传漏洞 1 x 无需用户验证的远程代码执行漏洞 1x 身份验证命令执行漏洞

漏洞影响范围

涉及西部数据以下型号系列的NAS设备

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

后续的补丁更新和相关情况,请继续关注我们的Twitter @exploiters

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2017-03-12,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 FreeBuf 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
Swift专题讲解二十二——泛型 原
        泛型是Swift语言强大的核心,泛型是对类型的抽象,使用泛型开发者可以更加灵活方便的表达代码意图。我们知道,有参函数的参数必须有一个明确的参数类型,有些时候开发者会遇到这样一种情况,编写一个函数用于交换两个变量的值,由于变量有类型之分,实现相同的功能,可能需要重载成多个函数来实现,这大大浪费了开发成本,使用泛型,可以完美的解决这个问题,示例代码如下:
珲少
2018/08/15
3070
iOS面试题-Swift篇
面试题持续整理更新中,如果你正在面试或者想一起进阶,不妨添加一下交流群 1012951431一起交流。
会写bug的程序员
2020/06/28
3.7K0
iOS面试题-Swift篇
swift 泛型
这个协议没有指定元素必须是何种类型,为了满足这三个条件,Container 协议需要在不知道容器中元素的具体类型的情况下引用这种类型。Container 协议需要指定任何通过 append(_:) 方法添加到容器中的元素和容器中的元素是相同类型,并且通过容器下标返回的元素的类型也是这种类型,为了达到这个目的,Container 协议声明了一个关联类型 ItemType,写作 associatedtype ItemType。这个协议无法定义 ItemType 是什么类型的别名,这个信息将留给遵从协议的类型来提供
xy_ss
2023/11/22
1670
swift 访问控制(open、public、internal、fileprivate、private)
注意 为了简单起见,对于代码中可以设置访问级别的特性(属性、基本类型、函数等),在下面的内容中我们会称之为“实体”
xy_ss
2023/11/22
8660
Swift 如何使用 Access Control
访问控制可以限制别的源文件或者模块来访问你的代码。该特性可以让你隐藏代码的具体实现,从而使代码有更好的封装性。
网罗开发
2021/02/26
8610
Swift基础 访问控制
翻译自:https://docs.swift.org/swift-book/LanguageGuide/AccessControl.html
郭顺发
2023/07/17
1980
Swift基础 通用
翻译自:https://docs.swift.org/swift-book/LanguageGuide/Generics.html
郭顺发
2023/07/17
1660
Swift学习总结
5、switch语法与objc差别很大,执行一个分支马上停止,不需要break语句跳出,反而想要穿透到下面分支还要用fallthrough语句。
SheltonWan
2019/06/06
3.1K0
Swift学习总结
Swift进阶八——泛型
当你扩展一个泛型类型的时候,不需要在扩展的定义中提供类型形式参数列表。原始类型定义的类型形式参数列表在扩展体里面仍然有效,并且原始类型形式参数列表名称也用于扩展类型形式参数。
拉维
2021/02/15
8260
Swift学习笔记
这是一篇学习swift的笔记 Objective-C是很好的语言,Runtime机制、消息机制等也是爱不释手。 Swift一直在更新,闲暇时间学一遍。学习的Blog:《从零开始学swift》 以下代码全部在playground进行的尝试 变量 let 是常量 var 是变量 不能修改的使用常量可以提高程序的可读性。 var str = "Hello, playground" print(str) let constA:Int = 12 let constB = 12 let constC = 12
落影
2018/04/27
1.4K0
Swift学习笔记
23.Swift学习之访问权限、异常
模块和源文件 模块——是单一的代码分配单元,一个框架或应用程序会作为的独立的单元构建和发布并且可以使用 Swift 的 import 关键字导入到另一个模块。 源文件是一个模块中的单个 Swift 源代码文件。 访问权限 open 和 public :允许实体被定义模块中的任意源文件访问,同样可以被另一模块的源文件通过导入该定义模块来访问。在指定框架的公共接口时,通常使用 open 或 public。 internal :允许实体被定义模块中的任意源文件访问,但不能被该模块之外的任何源文件访问。通常在
YungFan
2018/11/21
6700
Swift入门:访问控制
大多数情况下,您不需要指定访问控制,但有时您会希望显式地将属性设置为私有,因为它会阻止其他人直接访问它。这是很有用的,因为您自己的方法可以使用该属性,但其他方法不能,从而迫使它们通过您的代码执行某些操作。
韦弦zhy
2020/03/19
9440
iOS 面试策略之语言工具-Swift
本章节主要针对 iOS 的主流开发语言 Objective-C 和 Swift 进行分析和对比,同时也整理了 Xcode 编辑器的使用技巧和经验。
会写bug的程序员
2021/04/27
1.4K0
iOS 面试策略之语言工具-Swift
Swift| 基础语法(三)
总结下 swift下的基础语法,里面涉及到:常量&变量、Swift中的数据类型、逻辑分支、循环、字符串相关、数组和字典、方法的书写调用等内容,考虑到阅读体验分多篇来展示,希望对大家学习swift有所帮助,同时也是对自己的一个总结。
進无尽
2018/09/12
1.5K0
Swift| 基础语法(三)
Swift4.0 访问权限
    目前有 open  public  internal  fileprivate  private 这五个访问权限,都可以修饰属性和方法。下面通过例子来分析五个访问权限的使用。
星宇大前端
2019/01/15
8020
窥探Swift之类的继承与类的访问权限
  上一篇博客《窥探Swift之别具一格的Struct和Class》的博客可谓是给Swift中的类开了个头。关于类的内容还有很多,今天就来搞一下类中的继承以及类的访问权限。说到类的继承,接触过面向对象编程(OOP)的小伙伴并不陌生,继承就是OOP编程中几大特征之一,所以还是有必要把类的继承拎出来聊聊的。说到访问权限,这个在OOP编程中也是不可或缺的。如果你接触过其他OOP的语言,你应该对private, public, protected并不陌生。在Swift这么面向对象的编程语言中,也有类似的概念,不过其
lizelu
2018/01/11
1.5K0
窥探Swift之类的继承与类的访问权限
Swift 进阶: 泛型
泛型代码让你能根据你所定义的要求写出可以用于任何类型的灵活的、可复用的函数。你可以编写出可复用、意图表达清晰、抽象的代码。
Swift社区
2021/11/26
1.8K0
Swift 进阶: 泛型
swift方法调度总结
2、编译sil文件 从终端进入到ClassPerson.swift目录下,在同级目录下生成sil文件。
用户6094182
2022/09/28
5290
swift方法调度总结
戴铭的 Swift 小册子
越来越多同学打算开始用 Swift 来开发了,可很多人以前都没接触过 Swift。这篇和我以前文章不同的是,本篇只是面向 Swift 零基础的同学,内容主要是一些直接可用的小例子,例子可以直接在工程中用或自己调试着看。
Swift社区
2021/12/06
2.3K0
戴铭的 Swift 小册子
Swift---泛型(Generics)
泛型使您能够编写灵活的、可重用的功能和类型的代码。 例如要交换两个变量值的问题 不用泛型 //Int类型交换 func swapTwoInts(inout a: Int, inout b: Int){ let temp = a a = b b = temp } var someInt = 3 var anotherInt = 107 swapTwoInts(&someInt, &anotherInt) println("someInt is now \(someInt), and ano
用户3004328
2018/09/06
3940
相关推荐
Swift专题讲解二十二——泛型 原
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档