1.2 使用网站接口控制照明
理解底层技术架构是发现安全漏洞的一个好方法,而用例分析又是其中的最佳途径之一。调色照明系统最基本的用例是通过网站接口,在线注册一个账号,并将网桥链接至该账号下。一旦完成注册,用户就能够使用她的账号远程控制照明。本节,我们来看看系统是如何将用户账号与网桥关联起来的,以及如何在网站上控制照明。当我们明白了这一用例设计的实现原理之后,就会讨论相关的安全问题,以及如何利用这些安全漏洞。
首先,每个用户都必须在调色照明门户网站上注册一个免费账号,如图1-2所示。注册时,用户需要提供姓名、电子邮件地址,并创建一个至少6个字符长的密码。
图1-2:调色照明网站账户注册
第二步,网站尝试定位本地网桥,并将网桥与刚刚创建的账号关联起来。完成之后,网站会显示一条消息“发现网桥”(We found your bridge),如图1-3所示。
图1-3:通过网站关联网桥
网桥按设定会主动连接调色照明网站后台,并广播它的id(该id是手工分配给物理网桥的唯一标识符)、内部IP地址和MAC地址,所以网站知道如何定位网桥。网桥通过向dcs.cb.philips.com网站发送一个POST请求来完成这一步,POST请求示例如下:
POST /Dcs.ConnectionServiceHTTP/1.0
Host: dcs.cb.philips.com:8080
Authorization: CBAuth Type="SSO", Client="[DELETED]", RequestNr="16",
Nonce="[DELETED]", SSOToken="[DELETED]", Authentication="[DELETED]
Content-Type: application/CB-MessageStream; boundary=ICPMimeBoundary
Transfer-Encoding: Chunked
304
--ICPMimeBoundary
Content-Type: application/CB-Encrypted; cipher=AES
Content-Length:0000000672
[DELETED]
服务器端响应信息如下:
HTTP/1.0 200 OK
WWW-Authenticate : CBAuth Nonce="[DELETED]"
Connection : close
Content-Type : application/CB-MessageStream; boundary="ICPMimeBoundary"
Transfer-Encoding : Chunked
001
代码中,标记为[DELETED]的内容表示:为了保护硬件和被测试账户的机密性与完整性,该部分内容实际上已经删除了。删除的字符不会影响我们对该示例的理解。
PSOT请求的001响应表示调色基础设施已经关联了HTTP链接的源IP地址,完成了网桥的注册。
完成调色照明系统安装之后,你可以通过浏览网站https://www.meethue.com/api/nupnp获取网桥提交给调色基础设施的信息。如图1-4所示,你会看到网桥的id,以及它的MAC地址和内部IP地址。调色网站维护着一个网桥的列表(基于它们的id、内部IP地址和MAC地址),以及与此相对应的TCP连接(当你访问调色网站时)的源IP地址。这就是网站能确信显示“发现网桥”的原因,如图1-3所示。
要想获取远程访问网桥的权限,用户必须在30秒内按下网桥的按钮。这是一层额外的安全保护,目的是为了向服务器端证明用户有访问网桥的物理权限。
显示图1-3所示的消息之后,网站会发布如下GET请求:
图1-4:网桥id、内部IP地址和MAC地址
GET /en-US/user/isbuttonpressed HTTP/1.1
Host: www.meethue.com
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_3) AppleWebKit/536.28.10
(KHTML, like Gecko) Version/6.0.3 Safari/536.28.10
Accept: */*
DNT: 1
X-Requested-With: XMLHttpRequest
Referer: https://www.meethue.com/en-US/user/linkbridge
Accept-Language: en-us
Accept-Encoding: gzip, deflate
Cookie:[DELETED]
Connection: keep-alive
Proxy-Connection: keep-alive
GET请求要等待30秒,以确保用户有时间按下网桥上的按钮。用户按下按钮之后,网桥就会向网站dcp.cpp.philips.com发出一个标识按下按钮事件的POST请求。这时,在用户证实了他确实是网桥的拥有者之后,服务器会主动对刚才的POST请求做出响应:
HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8
Cache-Control: no-cache
Expires: Thu, 01 Jan 1970 00:00:00 GMT
Set-Cookie: PLAY_FLASH=;Path=/;Expires=Thu, 01 Jan 1970 00:00:00 GMT
Set-Cookie: PLAY_ERRORS=;Path=/;Expires=Thu, 01 Jan 1970 00:00:00 GMT
Set-Cookie: [DELETED]
Vary: Accept-Encoding
Date: Mon, 29 Apr 2013 23:30:06 GMT
Server: Google Frontend
Content-Length: 4
True
服务器给出的响应意味着用户确实按下了按钮。这时,浏览器会发出如下所示的GET请求以完成设置任务:
GET /en-US/user/setupcomplete HTTP/1.1
Host: www.meethue.com
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_3)
AppleWebKit/536.28.10
(KHTML, like Gecko) Version/6.0.3 Safari/536.28.10
Accept: text/html,application/xhtml+xml,application/xml;
DNT: 1
Referer: https://www.meethue.com/en-US/user/linkbridge
Accept-Language: en-us
Accept-Encoding: gzip, deflate
Cookie: [DELETED]
Connection: keep-alive
Proxy-Connection: keep-alive
服务器对GET请求做出响应,具体细节如下:
HTTP/1.1 200 OK
Content-Type: text/html; charset=utf-8; charset=utf-8
Cache-Control: no-cache
Expires: Thu, 01 Jan 1970 00:00:00 GMT
Set-Cookie: PLAY_FLASH=;Path=/;Expires=Thu, 01 Jan 1970 00:00:00 GMT
Set-Cookie: PLAY_ERRORS=;Path=/;Expires=Thu, 01 Jan 1970 00:00:00 GMT
Set-Cookie: PLAY_SESSION="[DELETED]-%00ip_address%3A[DELETED]__[DELETED]
;Path=/
Vary: Accept-Encoding
Date: Mon, 29 Apr 2013 23:30:08 GMT
Server: Google Frontend
Content-Length: 47369
[DELETED]
app.data.bridge = {"clientMessageState":[DELETED],"config":{"lights":{"15":
{"name":"Bathroom 2","state":{"bri":254,"effect":"none","sat":144,"reachabl
e":true,"alert":"none","hue":14922,"colormode":"ct","on":false,"ct":369,"xy
":[0.4595,0.4105]},"modelid":"LCT001","swversion":"65003148","pointsymbol":
{"3":"none","2":"none","1":"none","7":"none","6":"none","5":"none","4":"non
e","8":"none"},"type":"Extended color light"},"13":{"name":"Bathroom 4","st
ate":{"bri":254,"effect":"none","sat":144,"reachable":true,"alert":"none","
hue":14922,"colormode":"ct","on":false,"ct":369,"xy":[0.4595,0.4105]},"mode
lid":"LCT001","swversion":"65003148","pointsymbol":{"3":"none","2":"none","
1":"none","7":"none","6":"none","5":"none","4":"none","8":"none"},"type":"E
xtended color light"},"14":{"name":"Bathroom 3","state":{"bri":254,"effect"
:"none","sat":144,"reachable":true,"alert":"none","hue":14922,"colormode":"
ct","on":false,"ct":369,"xy":[0.4595,0.4105]},"modelid":"LCT001","swversion
":"65003148","pointsymbol":{"3":"none","2":"none","1":"none","7":"none","6"
:"none","5":"none","4":"none","8":"none"},"type":"Extended color light"},"1
1":{"name":"Hallway 2","state":{"bri":123,"effect":"none","sat":254,"reacha
ble":true,"alert":"none","hue":17617,"colormode":"xy","on":false,"ct":424,"
xy":[0.492,0.4569]},"modelid":"LCT001","swversion":"65003148","pointsymbol"
:{"3":"none","2":"none","1":"none","7":"none","6":"none","5":"none","4":"no
ne","8":"none"},"type":"Extended color light"},"12":{"name":"Bathroom 1","s
tate":{"bri":254,"effect":"none","sat":144,"reachable":true,"alert":"none",
"hue":14922,"colormode":"ct","on":false,"ct":369,"xy":[0.4595,0.4105]},"mod
elid":"LCT001","swversion":"65003148","pointsymbol":{"3":"none","2":"none",
"1":"none","7":"none","6":"none","5":"none","4":"none","8":"none"},"type":"
Extended color light"},"3":{"name":"Living room lamp 2","state":{"bri":102,
"effect":"none","sat":234,"reachable":true,"alert":"none","hue":687,"colorm
ode":"xy","on":false,"ct":500,"xy":[0.6452,0.3312]},"modelid":"LCT001","swv
ersion":"65003148","pointsymbol":{"3":"none","2":"none","1":"none","7":"non
e","6":"none","5":"none","4":"none","8":"none"},"type":"Extended color ligh
t"},"2":{"name":"Living room lamp 1","state":{"bri":119,"effect":"none","sa
t":180,"reachable":true,"alert":"none","hue":51616,"colormode":"xy","on":fa
lse,"ct":158,"xy":[0.3173,0.187]},"modelid":"LCT001","swversion":"65003148"
,"pointsymbol":{"3":"none","2":"none","1":"none","7":"none","6":"none","5":
"none","4":"none","8":"none"},"type":"Extended color light"},"1":{"name":"B
ookshelf 1","state":{"bri":161,"effect":"none","sat":236,"reachable":true,"
alert":"none","hue":696,"colormode":"xy","on":false,"ct":500,"xy":[0.6474,0
.3308]},"modelid":"LCT001","swversion":"65003148","pointsymbol":{"3":"none"
,"2":"none","1":"none","7":"none","6":"none","5":"none","4":"none","8":"non
e"},"type":"Extended color light"},"10":{"name":"Bedroom 1","state":{"bri":
254,"effect":"none","sat":144,"reachable":true,"alert":"none","hue":14922,"
colormode":"ct","on":false,"ct":369,"xy":[0.4595,0.4105]},"modelid":"LCT001
","swversion":"65003148","pointsymbol":{"3":"none","2":"none","1":"none","7
":"none","6":"none","5":"none","4":"none","8":"none"},"type":"Extended colo
r light"},"7":{"name":"Guest bedroom 1","state":{"bri":115,"effect":"none",
"sat":144,"reachable":true,"alert":"none","hue":14922,"colormode":"xy","on"
:false,"ct":369,"xy":[0.2567,0.2172]},"modelid":"LCT001","swversion":"65003
148","pointsymbol":{"3":"none","2":"none","1":"none","7":"none","6":"none",
"5":"none","4":"none","8":"none"},"type":"Extended color light"},"6":{"name
":"Kitchen 3","state":{"bri":74,"effect":"none","sat":253,"reachable":true,
"alert":"none","hue":37012,"colormode":"xy","on":false,"ct":153,"xy":[0.281
,0.2648]},"modelid":"LCT001","swversion":"65003148","pointsymbol":{"3":"non
e","2":"none","1":"none","7":"none","6":"none","5":"none","4":"none","8":"n
one"},"type":"Extended color light"},"5":{"name":"Kitchen 1","state":{"bri"
:106,"effect":"none","sat":254,"reachable":true,"alert":"none","hue":25593,
"colormode":"xy","on":false,"ct":290,"xy":[0.4091,0.518]},"modelid":"LCT001
","swversion":"65003148","pointsymbol":{"3":"none","2":"none","1":"none","7
":"none","6":"none","5":"none","4":"none","8":"none"},"type":"Extended colo
r light"},"4":{"name":"Bookshelf 2","state":{"bri":16,"effect":"none","sat"
:247,"reachable":true,"alert":"none","hue":11901,"colormode":"xy","on":fals
e,"ct":500,"xy":[0.5466,0.4121]},"modelid":"LCT001","swversion":"65003148",
"pointsymbol":{"3":"none","2":"none","1":"none","7":"none","6":"none","5":"
none","4":"none","8":"none"},"type":"Extended color light"},"9":{"name":"Ki
tchen 2","state":{"bri":246,"effect":"none","sat":216,"reachable":true,"ale
rt":"none","hue":58013,"colormode":"xy","on":false,"ct":359,"xy":[0.4546,0.
2323]},"modelid":"LCT001","swversion":"65003148","pointsymbol":{"3":"none",
"2":"none","1":"none","7":"none","6":"none","5":"none","4":"none","8":"none
"},"type":"Extended color light"},"8":{"name":"Hallway 1","state":{"bri":9,
"effect":"none","sat":254,"reachable":true,"alert":"none","hue":25593,"colo
rmode":"xy","on":false,"ct":290,"xy":[0.4091,0.518]},"modelid":"LCT001","sw
version":"65003148","pointsymbol":{"3":"none","2":"none","1":"none","7":"no
ne","6":"none","5":"none","4":"none","8":"none"},"type":"Extended color lig
ht"}},"schedules":{},"config":{"portalservices":true,"gateway":"192.168.2.1
","mac":"[DELETED]","swversion":"01005215","ipaddress":"192.168.2.2","proxy
port":0,"swupdate":{"text":"","notify":false,"updatestate":0,"url":""},"lin
kbutton":true,"netmask":"255.255.255.0","name":"Philips hue","dhcp":true,"U
TC":"2013-04-29T21:13:29","proxyaddress":"","whitelist":{"[DELETED]":{"name
":"iPad 4G","create date":"2012-11-23T05:54:57","last use date":"2013-02-11
T21:29:12"},"[DELETED]":{"name":"iPhone 5","create date":"2012-11-22T04:49:
57","last use date":"2012-12-03T01:21:56"},"[DELETED]":{"name":"iPhone 5","
create date":"2012-12-09T04:04:39","last use date":"2013-04-29T21:10:32"}}}
,"groups":{}},"lastHeardAgo":5 };app.data.bridgeid = "[DELETED]";[DELETED]
如上所示,HTTP响应包含灯泡和网桥的相关信息,包括状态信息以及内部网桥IP地址和id值。
注意响应信息中的whitelist项。该项中包含的字符串表示可用于直接发送网桥命令的授权令牌。下一节我们将详细讨论whitelisted项的使用。
这时,呈现给用户的页面是一个仪表盘,其中包含几个不同的场景(这些场景可方便地配置灯泡的颜色和亮度)以及一组灯泡的设置。如图1-5所示,用户可选择一个场景,针对某一个灯泡进行配置,也可以开、关所有的灯泡。在Web界面上,用户可以看到每种灯泡(如Bathroom 1)的状态信息。
图1-5:控制灯泡开关的仪表盘
当用户打算关闭所有的灯泡并点击off(关闭)按钮后,若用户网络与网桥在同一个局域网内,浏览器会直接连接网桥(本例中的IP地址为192.168.2.2):
PUT /api/[+whitelist DELETED+]/groups/0/action HTTP/1.1
Host: 192.168.2.2
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_3)
AppleWebKit/536.28.10
(KHTML, like Gecko) Version/6.0.3 Safari/536.28.10
Accept: */*
Accept-Language: en-us
Accept-Encoding: gzip, deflate
Connection: keep-alive
Proxy-Connection: keep-alive
Content-Length: 12
{"on":false}
如上所示,浏览器会发送网桥与用户账号关联时生成的whitelist令牌。/groups/0/action命令的详细说明请查阅飞利浦照明系统API文档的2.5节(免费注册后即可查阅该API文档),该命令用于关闭所有的灯泡。
如果用户远程连接网桥,与网桥不在一个本地局域网内,消息就需要经由Web服务器进行路由传递:
GET /en-US/user/sendMessageToBridge?clipmessage=%7B%22bridgeId%22%3A%22[DELETED]
%22%2C%22clipCommand%22%3A%7B%22url%22%3A%22%2Fapi%2F0%2Fgroups%2F0%2Faction%22%
2C%22method%22%3A%22PUT%22%2C%22body%22%3A%7B%22on%22%3Afalse%7D%7D%7D HTTP/1.1
Host: www.meethue.com
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_3)
AppleWebKit/536.28.10
(KHTML, like Gecko) Version/6.0.3 Safari/536.28.10
Accept: */*
DNT: 1
X-Requested-With: XMLHttpRequest
Referer: https://www.meethue.com/en-US/user/scenes
Accept-Language: en-us
Accept-Encoding: gzip, deflate
Cookie:[DELETED]
Connection: keep-alive
Proxy-Connection: keep-alive
注意,本例中clipCommand命令作为本地请求时,它的值也包含了相同的/groups/0/action命令。网桥会向/queue/getmessage?id=[DELETED id]&sso=[DELETED]发送一个POST请求,建立一个带外连接以搜集这些指令。一旦网桥处理完请求,服务器就会向浏览器发送一个响应确定所有的灯泡都关闭了:
HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8
Cache-Control: no-cache
Expires: Thu, 01 Jan 1970 00:00:00 GMT
Set-Cookie: PLAY_FLASH=;Path=/;Expires=Thu, 01 Jan 1970 00:00:00 GMT
Set-Cookie: PLAY_ERRORS=;Path=/;Expires=Thu, 01 Jan 1970 00:00:00 GMT
Set-Cookie: PLAY_SESSION=[DELETED];Path=/
Vary: Accept-Encoding
Date: Sun, 05 May 2013 23:04:19 GMT
Server: Google Frontend
Content-Length: 41
{"code":200,"message":"ok","result":"ok"}
message和result对应的代码都是ok,这意味着命令执行成功,灯泡都关闭了。
1.2.1信息泄露
将照明系统网站与网桥关联起来的Web服务器(网桥也有一个Web服务器在TCP的80端口监听信息)在对请求做出响应时,包含如下头信息:
Access-Control-Allow-Origin: *
基于浏览器的跨域策略(cross-origin policy),该信息头允许因特网上任何网站的JavaScript代码都可以获取运行照明系统网站的服务器及网桥的信息。这也导致了外部的实体有能力获取安装了照明系统的网段内的用户信息,同样也可以获取网桥的id、MAC地址和内部IP地址。
为了描述这种情况,我们来看看如下HTML代码:
<HTML>
<SCRIPT>
// Create the XHR object.
function find_hue()
{
varurl = 'https://www.meethue.com/api/nupnp';
varxhr = new XMLHttpRequest();
xhr.open('GET', url, true);
xhr.onload = function()
{
var text = xhr.responseText;
varobj=JSON.parse(text.substr(1,
text.length-2));
document.write('<H3>Your Hue bridge id
is '+ obj.id + '</H3><BR>');
document.write('<H3>Your Hue bridge
internal IP address is '+
obj.internalipaddress + '</H3><BR>');
document.write('<H3>Your Hue bridge MAC
address is '+ obj.macaddress + '</H3><BR>');
};
xhr.send();
}
find_hue();
</SCRIPT>
</HTML>
假定这段HTML代码运行在一个外部网站上。如图1-6所示,这个域名为www.dhanjani.com的网站能够获取网桥id、内部IP地址和MAC地址。如上述这段HTML代码所示,它是通过使用XMLHttpRequest对象获取这些信息的,XMLHttpRequest对象可以使Web浏览器连接到除www.dhanjani.com之外的一个域名上(例如www.meethue.com)。捕获了这些信息之后,外部网站的所有者就可以很轻松地保存这些信息了。
图1-6:信息泄露给外部网站
从安全的角度来讲,仅仅是随意地访问一个网站并不会获取到这些信息。我们将上述内容归结为信息泄露,因为它向一个没有得到数据拥有者授权的外部实体暴露了这些信息。
1.2.2 drive-by攻击
运行在网桥上的Web服务器也将Access-Control-Allow-Origin头设置为*。如果外部网站的所有者知道与该网桥关联的whitelist令牌,那么他就可以通过执行XMLHttpRequest对象请求获取网桥的内部IP地址(也就是前面我们提到过的内部IP地址)以达到远程控制灯光的目的,进而他可以针对网桥IP地址执行一个带有PUT命令的XMLHttpRequest对象请求:
xhr.open('PUT', 'http://'+obj.internalipaddress+'/api/[whitelist DELETED]/groups/
0/action', true);
然后再发送PUT请求的实体内容:
xhr.send("{\"on\":false}");
这会导致被攻击者的浏览器直接连接位于本地网络的照明系统网桥,并发送关灯的命令。在这种情况下,攻击者可以远程利用被攻击者的浏览器进入本地网络内部(这就是所谓的drive-by攻击)。
其实恶意攻击的可能性并不高,因为攻击者必须知道一个whitelist令牌才能实施攻击。然而,将Access-Control-Allow-Origin头设置为*,仍然是一种非常糟糕的设计思路。良好的安全机制应当是禁止任意一个网站强制开灯或关灯,即使是网站所有者获取了whitelist令牌。
1.2.3弱密码复杂性与密码泄露
当用户使用有效身份认证登录之后,照明系统网站允许用户在家远程控制灯光。
如图1-7所示,照明系统网站仅要求密码长度超过6个字符。用户通常倾向于创建简单的易被猜测出来的密码,如123456(实际上,研究显示123456和password是最常用的密码)。
事实是,用户真的会选择使用类似的弱密码,安全架构师的职责就是让用户不会犯这样的错误。大多数人只会考虑当前设备和软件的工作状况,而忽略了未来潜在的负面影响。
尽管密码策略薄弱,网站还是可以制定策略,一分钟之内错误登录两次的账户会被锁死(如图1-8所示)。在用户密码不容易被猜测出来的情况下,这会降低暴力攻击成功的可能性。
然而,另一个严重的问题是:对不同的服务用户倾向于使用相同的身份认证。报告显示,密码泄露的主要因素是相同的密码使用频率过高。当攻击者攻陷了一个主网站之后,他就很容易使用弱口令和密码尝试登录照明系统网站。
这种情况风险非常高,因为攻击者只需要仔细搜寻已经泄露和公开的用户名(当用户名采用邮箱地址的形式时)和密码,然后在照明系统网站上做测试就可以了。通过这种方式,攻击者很容易收集到照明系统的账号,并有能力远程改变用户灯泡的状态。
图1-7:密码要求至少6个字符
图1-8:一分钟内登录失败两次账户被锁死
其他相关威胁还包括照明系统网站基础架构潜在漏洞,以及心怀不满的员工对系统进行破坏等。任意一种情况都会让潜在的攻击者拥有强大的能力。面对这些针对基础设施的可能攻击,飞利浦并没有公开其内部管理流程以及其他可采取的应对措施。而且飞利浦没有明确说明他们是如何保护存储在数据库中的密码的,也没有明确说明他们的员工是否可以访问这些密码。