Chapter 4. Blurred Lines—When the Physical Space Meets the Virtual Space

Android and iOS are the most popular smartphone operating systems in the world. In addition to many other uses, these phones are useful for their mapping functionality. Prior to 2007, when the first iPhone was released, Global Positioning System (GPS) functionality on phones was barely usable—most of us printed out directions on a sheet of paper using Yahoo! Maps or MapQuest. It’s only been a few years since we began to rely so much on the GPS abilities of our smartphones, yet it’s now hard to imagine how we got by in the past.

Many of the tools we now have at home are likely to go through the same revolution. As we’ve seen in the previous chapters, we are rapidly heading toward replacing offline devices such as traditional door locks, radio-based baby monitors, and lighting with IoT devices that can be accessed and controlled remotely. In a few years, similar to our current sentiments regarding GPS functionality on our smartphones, we are going to wonder how we were able to get by without being able to communicate with various things in our homes (such as door sensors, thermostats, and motion detectors) regardless of our location. The notion that we were once unable to tell remotely if we’d left our home’s front door unlocked will seem unfathomable.

SmartThings (acquired by Samsung in 2014) is one company that is trying to lead the dream of the IoT-connected home with its suite of products, such as the SmartSense Multi Sensor and SmartPower Outlet. The SmartThings store has a slew of products that individuals can buy and install themselves.

Given that SmartThings is so focused on enabling the IoT in the home, this chapter focuses on evaluating the security in the design of its products. It is important to identify companies like SmartThings and analyze what good and bad design principles are at work in their product lines. People are installing and using such devices now, and the accompanying security architecture is bound to set precedents and be leveraged in future versions of similar products.

A lot of the functionality of these products is also currently being used to ensure physical security—for example, when a house’s main door is unexpectedly opened at midnight, an alert might be sent to the homeowner’s smartphone. As such, it is urgent for us to evaluate the current state of security of such products, so we can learn how to secure them now and in the future.

The SmartThings system can be used to control IoT products developed by third parties too. Many companies are trying to figure out how to interoperate with devices manufactured by others, so it is important to learn how to make all of our devices work with one another securely. In this chapter, we will also take a look at the interoperability offered by SmartThings from a security perspective.

SmartThings

In this section, we will focus on the following components: the SmartSense Multi Sensor, the SmartThings app, and the SmartThings Hub. Given the various ways the SmartThings platform can be programmed using the app, our focus will be on testing the secure design of the platform by analyzing the design and functionality of the app.

The SmartSense Multi Sensor (Figure 4-1) is a multipurpose device that includes a temperature sensor, an accelerometer, and a magnetic open/close sensor for doors. In this chapter, we will focus on the use case of the SmartSense Multi Sensor being used to trigger an event when a particular door is opened or closed.

The SmartThings Hub (Figure 4-2) is the brain of the SmartThings platform. It connects to all the sensors (including some third-party devices), allowing the user to be notified of events that trigger based on the inputs the sensors receive. The Hub also connects to the SmartThings cloud infrastructure, allowing the user to program specific triggers when the sensors receive input.

aiot 0401
Figure 4-1. The SmartSense Multi Sensor
aiot 0402
Figure 4-2. The SmartThings Hub
Note

The SmartThings Hub uses the ZigBee protocol to communicate with the nearby devices. The focus of this chapter is to evaluate security design by analyzing the SmartThings app and the development environment. See Chapter 1 to learn how to capture and analyze ZigBee data.

The SmartThings app can be used to configure SmartThings devices and check their status. In Figure 4-3, the app shows that the SmartPower Outlet is toggled on and that the door to which the SmartSense Multi Sensor is attached is closed.

aiot 0403
Figure 4-3. The SmartThings iOS app

Users must register for a SmartThings account and sign in at the screen shown in Figure 4-4.

aiot 0404
Figure 4-4. SmartThings app login screen

When the user types in his credentials and presses Log In, the app sends the following POST request:

POST /oauth/token HTTP/1.1
Host: graph.api.smartthings.com
Accept: application/json
Proxy-Connection: keep-alive
X-ST-Client-DeviceModel: iPhone
X-ST-Api-Version: 2.1
Accept-Encoding: gzip, deflate
Accept-Language: en;q=1
X-ST-Client-AppVersion: 1.6.5
Content-Type: application/x-www-form-urlencoded; charset=utf-8
Content-Length: 191
User-Agent: SmartThings/1006 (iPhone; iOS 8.0.2; Scale/2.00)
X-ST-Client-OS: iOS 8.0.2
Connection: keep-alive

client_id=[DELETED]&client_secret=[DELETED]0&grant_type=password&
password=skeuomorphism&scope=mobile&username=scott.forstall@apple.com

The app uses the OAuth standard to submit the credentials and gain authorization. The client_id and client_secret values submitted by the app are always the same, so they can be considered public information. As expected, the combination of the username and password fields needs to be correct. Once the user submits the right credentials, the graph.api.smartthings.com server will respond in the following way:

HTTP/1.1 200 OK
Cache-Control: no-store
Content-Type: application/json
Date: Fri, 17 Oct 2014 04:46:45 GMT
Server: Apache-Coyote/1.1
Vary: Accept-Encoding
Content-Length: 135
Connection: keep-alive

{
  "access_token": "[DELETED]",
  "expires_in": 1576799999,
  "scope": "mobile",
  "token_type": "bearer"
}

The important token to note here is access_token, which the app will use to convince the graph.api.smartthings.com server that it has authorization. Anyone who knows this token can directly connect to the graph.api.smartthings.com server and impersonate the user. Note that the unit of expires_in is seconds, so this value correlates to 18,250 days. In other words, the access_token value is valid and will be accepted by graph.api.smartthings.com for 18,250 days, after which the user will be required to log in again.

The SmartThings app allows the user to specify multiple physical locations, such as home and office, and manage devices within those locations. Figure 4-5 shows the app interface listing a current location (Home) with the ability to add additional locations.

aiot 0405
Figure 4-5. SmartThings App interface for viewing and adding locations

To get the list of locations associated with the user, the app sends the following request:

GET /api/locations HTTP/1.1
Host: graph.api.smartthings.com
Accept: application/json
Authorization: Bearer [DELETED]
Proxy-Connection: keep-alive
X-ST-Client-DeviceModel: iPhone
X-ST-Api-Version: 2.1
Accept-Encoding: gzip, deflate
Accept-Language: en;q=1
X-ST-Client-AppVersion: 1.6.5
X-ST-Api-Key: [DELETED]
X-ST-Client-OS: iOS 8.0.2
User-Agent: SmartThings/1006 (iPhone; iOS 8.0.2; Scale/2.00)
Connection: keep-alive

The X-ST-Api-Key token is constant and can be considered public knowledge. The value submitted for Authorization is the access_token value that was received by the app upon successful authentication. The graph.api.smartthings.com server responds with the following:

HTTP/1.1 200 OK
Content-Type: application/json;charset=utf-8
Date: Fri, 17 Oct 2014 04:46:47 GMT
Server: Apache-Coyote/1.1
Vary: Accept-Encoding
X-Pad: avoid browser bug
Content-Length: 1204
Connection: keep-alive

[{"id":"[DELETED]","name":"Home","accountId":"[DELETED]","latitude":42.613706,
"longitude":-120.200028,"regionRadius":150,"backgroundImage":
"https://smartthings-location-images.s3.amazonaws.com/standard/standard62.jpg",
"mode":{"id":"[DELETED],"name":"Away","locationId":"[DELETED]"},"modes":
[{"id":"[DELETED]","name":"Away","locationId":"[DELETED]"},{"id":"
[DELETED]","name":"Home","locationId":"[DELETED]"},{"id":"[DELETED]","name":
"Night","locationId":"[DELETED]"}],"role":"owner","helloHomeAppId":"[DELETED]",
"temperatureScale":"F","hubs":[{"id":"[DELETED]","name":"Home","locationId":
"[DELETED]","firmwareVersion":"000.010.00246","zigbeeId":"[DELETED]","status":
"ACTIVE","onlineSince":"2014-10-08T18:42:52.679Z","signalStrength":null,
"batteryLevel":null,"type":{"name":"Hub"},"virtual":false,"role":"owner",
"firmwareUpdateAvailable":false}]}]

According to the response, one location is associated with this user’s account. This is identified by the value of the id token. The latitude and longitude values represent the actual physical location. There are also several modes, such as Away and Home. The user can manually set the current mode, or the SmartThings system can be configured to do it automatically, such as setting the value to Away when the user’s phone is outside of the regionRadius value of the location.

The SmartThings app now needs to pull additional information about the SmartThings devices associated with the account and their configurations. It does this by issuing the following POST request using the location id and access_token (for the Authorization field) obtained earlier:

GET /api/locations/[DELETED]/smartapps/ HTTP/1.1
Host: graph.api.smartthings.com
Accept: application/json
Authorization: Bearer [DELETED]
Proxy-Connection: keep-alive
X-ST-Client-DeviceModel: iPhone
X-ST-Api-Version: 2.1
Accept-Encoding: gzip, deflate
Accept-Language: en;q=1
X-ST-Client-AppVersion: 1.6.5
X-ST-Api-Key: [DELETED]
X-ST-Client-OS: iOS 8.0.2
User-Agent: SmartThings/1006 (iPhone; iOS 8.0.2; Scale/2.00)
Connection: keep-alive

And the server responds with the following:

HTTP/1.1 200 OK
Content-Type: application/json;charset=utf-8
Date: Fri, 17 Oct 2014 04:46:49 GMT
Server: Apache-Coyote/1.1
Vary: Accept-Encoding
X-Pad: avoid browser bug
Connection: keep-alive
Content-Length: 18488

[{"id":"[DELETED]","label":"Intruder alert","smartAppVersion":{"id":"[DELETED]"
,"version":0.9,"state":"SELF_APPROVED","name":"Smart Security","description":
"Alerts you when there are intruders but not when you just got up for a glass
of water in the middle of the night","iconUrl":"
https://s3.amazonaws.com/smartapp-icons/SafetyAndSecurity/App-IsItSafe.png",
"iconX2Url":
"https://s3.amazonaws.com/smartapp-icons/SafetyAndSecurity/App-IsItSafe@2x.png",
"dateCreated":"2013-05-29T11:58:02Z","lastUpdated":"2014-05-14T21:55:47Z",
"preferences":{"sections":[{"input":[{"title":[DELETED]],"hideable":false,
"hidden":false,"mobileOnly":true}],"defaults":true},"legacy":true,"pageCount":
0,"installedCount":1420,"author":"SmartThings","photoUrls":[],"videoUrls":[],
"showModuleWithoutChildren":false,"smartApp":{"id":"[DELETED]"}},
"installedSmartAppParentId":null,"settings":{"textMessage":"Intruder alert!",
"intrusionMotions":[],"alarms":[],"intrusionContacts":["[DELETED],"silent":
"Yes","newMode":"","residentMotions":[],"residentsQuietThreshold":"0","phone":
"4151111111","lights":[],"seconds":"0"}

Notice the Intruder alert customization, which sends an alert to the user’s phone using a text message (to phone number 4151111111 in this case) every time someone opens the main door (detected by an installed SmartThings Multi Sensor). Figure 4-6 shows the corresponding user interface on the app.

aiot 0406
Figure 4-6. SmartThings App configuration for “Intruder alert” customization

Now that the customization is set, the SmartThings app will send a text message to 4151111111 every time the door is opened. Figure 4-7 shows the text message (“Intruder alert!”) received by the user when the customization is triggered.

aiot 0407
Figure 4-7. Text message alerting user when door is opened

It isn’t hard to imagine the amount of trust a family would have to place in a product to depend on it to send an alert in the case of a physical intrusion. As such, it is important that companies such as SmartThings architect security into the design and functionality of their products. In the next few sections, we will look at scenarios that could put SmartThings customers at risk, and how the issues can be mitigated.

Hijacking Credentials

As we’ve seen, the SmartThings app stores the user’s settings and customizations on the external infrastructure available at graph.api.smartthings.com. This makes it possible for external entities to take control of a user’s SmartThings devices if they are able steal or guess the user’s password. Malicious entities that successfully do this can switch on or off appliances connected to a SmartPower Outlet or disable customizations associated with a SmartSense Multi Sensor.

As shown in Figure 4-8, app requires a password at least eight characters long, including at least one number and one letter.

aiot 0408
Figure 4-8. SmartThings app password requirements

Based on the complexity of the password requirements, SmartThings designers clearly intended to build in security. Complex passwords slow down attackers, who try to guess various combinations of possible passwords.

Users who forget their passwords can request a new one, as shown in Figure 4-9.

aiot 0409
Figure 4-9. Password reset request using the SmartThings app

As soon as the user presses the Send Recovery Email button, the app sends the email shown in Figure 4-10 to the specified address.

aiot 0410
Figure 4-10. Email from SmartThings allowing password reset

The “click here to reset your password” link is in following form:

http://mandrillapp.com/track/click/30028387/graph.api.smartthings.com
?p=sdf9234msafd0234ASFASDf234023042342masdf0234SDAFSDF0234msdf0asfdsd
f02342msad

When the user clicks on this link, the browser is redirected to the SmartThings website with a link such as this:

https://graph.api.smartthings.com/register/resetPassword?t=2304ksdf0As
dfa3sdfd4asfasdf

Upon redirection, the user is allowed to pick a new password, as shown in Figure 4-11.

aiot 0411
Figure 4-11. User picking a new password as part of the password recovery process

There are several security issues with the SmartThings authentication and authorization systems.

Single-factor authentication

Systems that protect against physical threats should not rely upon single-factor authentication. SmartThings markets its ability to secure and monitor the home as a primary feature. Even though the system has implemented a complex password requirement, one-time access to the owner’s email account can compromise the physical security promised by the system. It might be overkill to protect your Pizza Hut account with anything more than a username and password, since the cost of implementing extra measures might be higher than that caused by nefarious pizza-ordering activity. But a system you rely upon to protect your home and loved ones must offer greater security.

In the current situation, a malicious entity can use the password reset feature (Figure 4-9) to reset a victim’s SmartThings password. All the attacker needs is temporary access to the target’s email account, which can be gained by stealing a mobile device that belongs to the SmartThings user. The attacker can then reset the password (Figure 4-11) just by using the user’s preconfigured email client on the mobile device. Even without physical access to the mobile device, the attacker could obtain access to the email account by launching a phishing attack or successfully infecting the victim’s computer or phone with malware that captures email credentials.

The point here is that products that advertise physical security should take security seriously and implement tight controls. Millions of people have their email credentials compromised every week. Users should not have to worry about an intruder being able to monitor and influence the devices in their homes remotely just because they have fallen victim to a simple phishing attack.

Companies such as Google and Apple have realized that it is becoming harder to guarantee customer security by relying on a username and password mechanism alone. Google offers two-factor authentication, which requires the use of a password (first factor) in addition to the possession of a mobile device (second factor).

With two-factor authentication enabled, the user must first enter his credentials, after which a randomly generated code is sent as a text message to the user’s phone. The user must also enter this code to log into the account. This type of setup requires knowledge of something secret (the password), along with the possession of a physical object (the mobile device).

Apple has implemented a similar method to protect its users and has also opened up its TouchID system to third-party app developers. This system could easily be leveraged by the SmartThings app to verify the user’s fingerprint as the second factor.

Another issue of concern is the longevity (18,250 days!) of the access_token discussed earlier. Since 18,250 days equals approximately 50 years, a potential attacker has five decades to try to obtain the access_token and reuse it to launch commands using the graph.api.smartthings.com service.

We hope that SmartThings and other emerging IoT manufacturers will enhance their designs to implement two-factor authentication, so that attackers won’t be able to disrupt physical safety using traditional attack vectors such as phishing and infecting desktops with malware.

Clear-text password reset link

The clear-text password reset link sent by the SmartThings app can be abused to hijack the user’s credentials. As shown in Figure 4-10, a user who requests a password reset is sent a password recovery email containing a link to click (Figure 4-9). This link (in the form of http://mandrillapp.com/track/click/30028387/graph.api.smartthings.com, as discussed earlier) does not use Transport Layer Security (TLS), but rather is sent across the local network and the Internet in the clear.

The user is then redirected to a link that does use TLS (in the form of https://graph.api.smartthings.com/register/resetPassword, also as discussed earlier). However, anyone on the local WiFi network, such as a public wireless network in a cafe, can capture the original link if the user clicks on it. Once this link has been captured, the attacker can reset the password by submitting a new password before the victim does. Once the password is reset, the password reset link expires and the user will have to submit a new request.

In this case, an argument could be made that it would be hard for a potential attacker to wait around for the victim to forget her password and submit a reset request at a cafe. However, in the case of a targeted attack in which the attacker is on the same wireless network as the victim, the attacker can initiate the password reset by submitting the request shown in Figure 4-9 on behalf of the user. In that case, the victim would likely be surprised by the password reset email but might assume there is a glitch in the SmartThings system and go ahead with the reset process anyway, allowing the attacker to capture the initial link and take over the account. In addition to this scenario, individuals with access to the network devices between the victim and mandrillapp.com can also capture the initial link and compromise the user’s SmartThings account.

Abusing the Physical Graph

The upcoming age of the IoT is bound to connect our physical world with our online virtual spaces. We have already witnessed this occurring throughout the previous chapters of this book: being able to control lightbulbs based on triggers on Facebook using IFTTT, using our mobile devices to send our companions electronic keys that can be used to open physical doors, and storing information about our physical IoT objects on remote servers like graph.api.smartthings.com.

The SmartThings team has published a vision of its notion of a “physical graph” that will serve as a platform for IoT objects in the future:

At SmartThings, we believe the next and perhaps most life-altering evolution of the Internet will be the creation of the physical graph; the digitization, connectivity and programmability of the physical world around us. Whether you call this the Internet of Things, sensor networks or home and life automation, the implications for how we live, work, and have fun are profound. At our core, we also believe that for the ecosystem to be healthy, it must be open. An open physical graph is the only way to bridge the innovation, inventions and brilliance of the many device manufacturers, hardware makers, developers, and everyday people who are working to change our lives today and in the future.

SmartThings has brought its vision of “connectivity and programmability of the physical world” to life using a web-based integrated development environment (IDE). Using this free tool, users can easily program their IoT devices to perform tasks tailored to their personal specifications.

Anyone can sign up for a free SmartThings developer account and start using the IDE to create programs to control IoT devices. As shown in Figure 4-12, developers can quickly start building programs by selecting from a variety of Example SmartApps.

aiot 0412
Figure 4-12. The SmartThings IDE

It is great that the SmartThings team has decided to open up a free tool to its users and developers, but from a security perspective, it becomes important to make sure the platform cannot be abused by malicious entities. For example, take a look at the Text Me When It Opens program available from the Example SmartApps library:

/**
 *  Text Me When It Opens
 *
 *  Author: SmartThings
 */
definition(
    name: "Text Me When It Opens",
    namespace: "smartthings",
    author: "SmartThings",
    description: "Get a text message sent to your phone when an open/close sensor
    is opened.",
    category: "Convenience",
    iconUrl: "https://s3.amazonaws.com/smartapp-icons/Meta/window_contact.png",
    iconX2Url: "https://s3.amazonaws.com/smartapp-icons/Meta/
    window_contact@2x.png"
)

preferences {
    section("When the door opens...") {
		input "contact1", "capability.contactSensor", title: "Where?"
	}
	section("Text me at...") {
		input "phone1", "phone", title: "Phone number?"
	}
}

def installed()
{
	subscribe(contact1, "contact.open", contactOpenHandler)
}

def updated()
{
	unsubscribe()
	subscribe(contact1, "contact.open", contactOpenHandler)
}

def contactOpenHandler(evt) {
	log.trace "$evt.value: $evt, $settings"
	log.debug "$contact1 was opened, texting $phone1"
	sendSms(phone1, "Your ${contact1.label ?: contact1.name} was opened")
}

This program sets up a virtual contact (emulating the SmartSense Multi Sensor) that can be toggled using the IDE. Once this contact is toggled to the open state, the code in contactOpenHandler(evt) is invoked, which in turn invokes the sendSms service to send a text message.

Take a look at Figure 4-7 again. Notice that the SmartThings service uses a short code (like a phone number, but specific to text messages) of 512-69. If anyone in the world (even those who don’t own a single SmartThings product) were to sign up for a free SmartThings developer account and use the Text Me When It Opens program, they could use this testing functionality to send any text message to anyone in the world, and it would also appear as originating from the short code 512-69.

Now imagine if someone were to change the sendSms code to the following:

sendSms(phone1, "WARNING: Systems malfunction. All devices disarmed.
Possible intruder activity.")

In this case (Figure 4-13), the user will get a text message with the scary warning from the same 512-69 short code. Imagine getting such a text message after midnight, while you are sleeping or perhaps even away from home. Users that have gotten previous text messages from the SmartThings system will be likely to trust the message, because it originates from the same short code. In fact, when the short code used by SmartThings recently changed (to 512-69), users inquired about the change on discussion forums, indicating that they are indeed aware of and trust messages that originate from the code.

Many users might choose to use push notification services such as Apple Push Notification and Google Cloud Messaging to receive the notifications, instead of text messages. However, others prefer text messages, and SmartThings recommends them when it needs to shut down non–text-based notifications for maintenance, as shown in an actual announcement in Figure 4-14. Such intervals are the perfect time for intruders to abuse the situation.

This is just one example of how such a system can be abused. A malicious person who knows your cell phone number and knows that you rely on SmartThings products for remote monitoring to ensure the safety of your family could abuse this situation to cause you to leave a particular location (such as your office) and head home to check up on your family because you’ve received an SMS from the SmartThings short code.

In addition, spammers can abuse the free sendSms functionality to use the SmartThings short code to send free text advertisements to anyone.

The lesson here is that the incoming number associated with text messages should never be used to establish trust or prove authenticity. One solution is to request the user to input a four-digit number that will be reflected on every text message sent out by SmartThings. Users can be educated to disregard messages that do not contain the four-digit prefix. However, this places a greater burden on the users and complicates their interaction with the product. Still, this is the price to pay if traditional protocols such as text messaging are to be used.

aiot 0413
Figure 4-13. Scary text message to SmartThings user

Data-driven push notifications are much more reliable, because they rely on certificate-based encryption and authentication and are much harder to spoof.

aiot 0414
Figure 4-14. Email from SmartThings advising users of maintenance schedule

SmartThings SSL Certificate Validation Vulnerability

In March 2015, a report titled “SmartThings SSL Certificate Validation Vulnerability” exposed a critical issue relating to the SmartThings Hub:

The communications between the SmartThings Hub and the SmartThings backend servers is encrypted with SSL. However, the SSL client implementation in use does not validate the authenticity of the SSL certificate presented by the server during the initial handshake. An attacker with the ability to monitor and intercept traffic can present a “forged” SSL certificate to the Hub claiming to be a legitimate backend server, which the Hub will accept as genuine. This makes it possible to perform a “man-in-the-middle” attack, whereby an attacker relays communications between client and server without their knowledge. In this scenario, the communications are available to the attacker in an unencrypted form and may be modified or disrupted, effectively defeating the protections offered by SSL encryption.

Secure and authenticated communications are vital to a platform such as SmartThings, which may be used as part of a home security system. As an example, the Hub transmits a data packet when a SmartSense Open/Closed Sensor opens. By simply not relaying this data packet, an attacker can prevent notification of this event from ever reaching the SmartThings backend servers, which in turn prevents notification being delivered to the end user.

A potential mitigating factor is the lack of WiFi communication used by the Hub, making traffic interception more difficult as it requires that an attacker be physically connected to the same network as the Hub or for interception to occur during transit over the Internet. However this does not offer complete protection, as several home networks make use of WiFi bridges or repeaters. An attacker may also have compromised another device residing on the network such as a router or personal media server that may be used to perform traffic interception.

Security vulnerabilities such as this can allow an attacker on the same WiFi network (or on a device that is between the home network of the user and the route to the SmartThings network) to modify and influence all of the communication between the Hub and the SmartThings network. Attackers can abuse this vulnerability to trigger or deny alerts that the user might have set up, and this can put the physical safety of SmartThings customers at risk.

The good news is that the SmartThings team worked with the researchers who identified the problem and responded with a security patch:

11/10/14 - Initial report to vendor

11/11/14 - Report acknowledged

11/21/14 - Vulnerability confirmed

01/29/15 - Updated firmware rollout begins

03/04/15 - Public disclosure

The researchers of this vulnerability should also be given credit for having the patience to work with SmartThings and waiting for the patch to be rolled out before exposing the issue.

This is a good example of how a security issue in an IoT product can give rise to vulnerabilities that attackers can abuse to formulate man-in-the-middle attacks. However, this is also a great example of how IoT vendors, such as SmartThings, should work with security researchers to understand the issues and roll out firmware patches to protect their customers.

Interoperability with Insecurity Leads to…Insecurity

We have to give credit where credit is due. SmartThings should shore up the authentication capabilities for its suite of products and work on securely enabling traditional services such as text messaging its their free developer suite. That said, unlike the case of the Philips hue or Belkin WeMo products, the SmartThings architecture does not implicitly trust the local network.

In the case of the Belkin WeMo Baby and the WeMo Switch, any device on the same local network can readily connect to and instruct the devices without any further authentication. However, in the case of SmartThings, the Hub and the app establish outbound connections to graph.api.smartthings.com to communicate with each other. In this way, every update and instruction is validated against an established and authenticated session tied to the user’s SmartThings account. This makes the SmartThings approach more secure, because it doesn’t allow a workstation or other device on the network that has been infected with malware to directly manipulate SmartThings devices.

As mentioned earlier, in addition to its own devices, the SmartThings system now supports interoperability with third-party IoT devices. With SmartThings Labs, the SmartThings app and Hub can be used to control the Philips hue lighting system, the WeMo Switch, and other devices. Having given credit to SmartThings for securely routing information through graph.api.smartthings.com and not trusting the local network implicitly, we will analyze whether this secure design principle holds up by looking at how SmartThings interoperates with the Philips and Belkin products.

SmartThings and hue Lighting

Using the SmartThings app, it is possible to search for and connect to the Philips hue bridge (described in Chapter 1). In order to do this, touch the + button at the bottom of the Dashboard section of the SmartThings app. Next, select Light Bulbs → Philips hue Light Bulb. Once you do this, your screen should look like Figure 4-15.

The SmartThings Hub starts to look for a hue bridge on the local network by issuing the following SSDP query:

M-SEARCH * HTTP/1.1
MX: 1
MAN: "ssdp:discover"
HOST:239.255.255.250:1900
ST: urn:schemas-upnp-org:device:basic:1

The hue bridge responds to this query and identifies itself:

HTTP/1.1 200 OK
CACHE-CONTROL: max-age=100
EXT:
LOCATION: http://10.0.1.2:80/description.xml
SERVER: FreeRTOS/6.0.5, UPnP/1.0, IpBridge/0.1
ST: upnp:rootdevice

The SmartThings Hub now fetches /description.xml from the hue bridge by issuing the following GET request:

GET /description.xml HTTP/1.1
Accept: */*
User-Agent: Linux UPnP/1.0 SmartThings
HOST: 192.168.2.2:80
aiot 0415
Figure 4-15. SmartThings App connecting to a Philips hue bridge

To which the hue bridge responds:

HTTP/1.1 200 OK
Content-type: text/xml
Connection: Keep-Alive

<?xml version="1.0" encoding="UTF-8" ?>
<root xmlns="urn:schemas-upnp-org:device-1-0">
<specVersion>
<major>1</major>
<minor>0</minor>
</specVersion>
<URLBase>http://10.0.1.2:80/</URLBase>
<device>
<deviceType>urn:schemas-upnp-org:device:Basic:1</deviceType>
<friendlyName>Philips hue (10.0.1.2)</friendlyName>
<manufacturer>Royal Philips Electronics</manufacturer>
<manufacturerURL>http://www.philips.com</manufacturerURL>
<modelDescription>Philips hue Personal Wireless Lighting</modelDescription>
<modelName>Philips hue bridge 2012</modelName>
<modelNumber>929000226503</modelNumber>
<modelURL>http://www.meethue.com</modelURL>
<serialNumber>[DELETED]</serialNumber>
<presentationURL>index.html</presentationURL>
<iconList>
<icon>
<mimetype>image/png</mimetype>
<height>48</height>
<width>48</width>
<depth>24</depth>
<url>hue_logo_0.png</url>
</icon>
<icon>
<mimetype>image/png</mimetype>
<height>120</height>
<width>120</width>
<depth>24</depth>
<url>hue_logo_3.png</url>
</icon>
</iconList>
</device>
</root>

At this point, the user will see a notification that the bridge has been found, as shown in Figure 4-16.

When the Next button is pressed, the SmartThings Hub sends the following POST request to the hue bridge:

POST /api HTTP/1.1
Accept: */*
User-Agent: Linux UPnP/1.0 SmartThings
HOST: 10.0.1.2:80
Content-Type: application/json
Content-Length: 107

{"devicetype":"8f7ab27c-6c04-4378-b0b1-dcd4fd468815-0","username":"8f7ab27c-6c04
-4378-b0b1-dcd4fd468815-0"}
aiot 0416
Figure 4-16. SmartThings app locateing the hue bridge

The values for devicetype and username are the same and seem random enough in nature. Recall (from “Controlling Lights Using the iOS App”) that the user will have to prove physical ownership of the bridge by pressing the button on it within 30 seconds. When this happens, the hue bridge will accept the value of username, and it can subsequently be used by the SmartThings Hub to connect to the hue bridge on the local network and issue commands.

Assuming the user presses the button on the hue bridge, the following response is returned to the SmartThings Hub:

HTTP/1.1 200 OK
Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0
Pragma: no-cache
Expires: Mon, 1 Aug 2011 09:00:00 GMT
Connection: close
Access-Control-Max-Age: 3600
Access-Control-Allow-Origin: *
Access-Control-Allow-Credentials: true
Access-Control-Allow-Methods: POST, GET, OPTIONS, PUT, DELETE, HEAD
Access-Control-Allow-Headers: Content-Type
Content-type: application/json

[{"success":{"username":"8f7ab27c-6c04-4378-b0b1-dcd4fd468815-0}}]

The user will be notified that the connection was successful, as shown in Figure 4-17.

From now on, the SmartThings Hub can command the Philips hue bridge by always including the value of 8f7ab27c-6c04-4378-b0b1-dcd4fd468815-0 as the authorization token in the request. For example, it can issue a POST request of the form /api/8f7ab27c-6c04-4378-b0b1-dcd4fd468815-0/groups/0/action to turn off all the lights, as shown in “Controlling Lights Using the iOS App”.

Note

The hue bridge accepts incoming connections on port 80, which does not use encryption. This can allow a malicious device on the local network to launch ARP spoofing attacks and steal and proxy the username. However, this architecture is based on a design from the hue team. The SmartThings Hub has no choice but to use unencrypted communication, because the hue web server communicates only in clear text.

Recall from Chapter 1 that the earlier implementation of the hue app utilized the MD5 hash of the smartphone’s MAC address as the username. We know that was a bad idea, because it allowed any local device to cause a perpetual blackout. The SmartThings Hub does not commit this error. The SmartThings team should be complimented for designing this diligently.

aiot 0417
Figure 4-17. SmartThings Hub successfully gaining authorization from the hue bridge

SmartThings and the WeMo Switch

The WeMo Switch (see “Some Things Never Change: The WeMo Switch”) can also be controlled using the SmartThings app. Similar to setting up the hue bridge, the user has to select the + button on the bottom of the Dashboard screen of the app, followed by selecting Switches & Dimmers → Belkin WeMo Switch → Connect Now. This causes the SmartThings Hub to search for the switch using SSDP:

M-SEARCH * HTTP/1.1
MX: 1
MAN: "ssdp:discover"
HOST:239.255.255.250:1900
ST: urn:Belkin:device:controllee:1

The WeMo Switch responds to identify itself:

HTTP/1.1 200 OK
CACHE-CONTROL: max-age=86400
DATE: Mon, 20 Oct 2014 14:32:17 GMT
EXT:
LOCATION: http://192.168.2.10:49153/setup.xml
OPT: "http://schemas.upnp.org/upnp/1/0/"; ns=01
SERVER: Unspecified, UPnP/1.0, Unspecified
X-User-Agent: redsonic
ST: urn:Belkin:device:controllee:1

The app alerts the user that a WeMo Switch has been located, as shown in Figure 4-18.

As expected, the SmartThings Hub sends the following GET request to the WeMo Switch:

GET /setup.xml HTTP/1.1
HOST: C0A8020A:C001
aiot 0418
Figure 4-18. SmartThings app letting the user know that a WeMo Switch has been found

And the Switch responds:

HTTP/1.1 200 OK
CONTENT-LENGTH: 3767
CONTENT-TYPE: text/xml
DATE: Mon, 20 Oct 2014 14:32:23 GMT
LAST-MODIFIED: Mon, 20 Oct 2014 14:26:28 GMT
SERVER: Unspecified, UPnP/1.0, Unspecified
X-User-Agent: redsonic
CONNECTION: close

<?xml version="1.0"?>
<root xmlns="urn:Belkin:device-1-0">
  <specVersion>
    <major>1</major>
    <minor>0</minor>
  </specVersion>
  <device>
<deviceType>urn:Belkin:device:controllee:1</deviceType>
<friendlyName>WeMo Switch</friendlyName>
    <manufacturer>Belkin International Inc.</manufacturer>
    <manufacturerURL>http://www.belkin.com</manufacturerURL>
    <modelDescription>Belkin Plugin Socket 1.0</modelDescription>
    <modelName>Socket</modelName>
    <modelNumber>1.0</modelNumber>
    <modelURL>http://www.belkin.com/plugin/</modelURL>
<serialNumber>[DELETED]</serialNumber>
<UDN>[DELETED]</UDN>
    <UPC>123456789</UPC>
<macAddress>[DELETED]</macAddress>
<firmwareVersion>WeMo_US_2.00.2769.PVT</firmwareVersion>
<iconVersion>0|49153</iconVersion>
<binaryState>0</binaryState>
    <iconList>
      <icon>
        <mimetype>jpg</mimetype>
        <width>100</width>
        <height>100</height>
        <depth>100</depth>
         <url>icon.jpg</url>
      </icon>
    </iconList>
    <serviceList>
      <service>
        <serviceType>urn:Belkin:service:WiFiSetup:1</serviceType>
        <serviceId>urn:Belkin:serviceId:WiFiSetup1</serviceId>
        <controlURL>/upnp/control/WiFiSetup1</controlURL>
        <eventSubURL>/upnp/event/WiFiSetup1</eventSubURL>
        <SCPDURL>/setupservice.xml</SCPDURL>
      </service>
      <service>
        <serviceType>urn:Belkin:service:timesync:1</serviceType>
        <serviceId>urn:Belkin:serviceId:timesync1</serviceId>
        <controlURL>/upnp/control/timesync1</controlURL>
        <eventSubURL>/upnp/event/timesync1</eventSubURL>
        <SCPDURL>/timesyncservice.xml</SCPDURL>
      </service>
      <service>
        <serviceType>urn:Belkin:service:basicevent:1</serviceType>
        <serviceId>urn:Belkin:serviceId:basicevent1</serviceId>
        <controlURL>/upnp/control/basicevent1</controlURL>
        <eventSubURL>/upnp/event/basicevent1</eventSubURL>
        <SCPDURL>/eventservice.xml</SCPDURL>
      </service>
      <service>
        <serviceType>urn:Belkin:service:firmwareupdate:1</serviceType>
        <serviceId>urn:Belkin:serviceId:firmwareupdate1</serviceId>
        <controlURL>/upnp/control/firmwareupdate1</controlURL>
        <eventSubURL>/upnp/event/firmwareupdate1</eventSubURL>
        <SCPDURL>/firmwareupdate.xml</SCPDURL>
      </service>
      <service>
        <serviceType>urn:Belkin:service:rules:1</serviceType>
        <serviceId>urn:Belkin:serviceId:rules1</serviceId>
        <controlURL>/upnp/control/rules1</controlURL>
        <eventSubURL>/upnp/event/rules1</eventSubURL>
        <SCPDURL>/rulesservice.xml</SCPDURL>
      </service>
.
      <service>
        <serviceType>urn:Belkin:service:metainfo:1</serviceType>
        <serviceId>urn:Belkin:serviceId:metainfo1</serviceId>
        <controlURL>/upnp/control/metainfo1</controlURL>
        <eventSubURL>/upnp/event/metainfo1</eventSubURL>
        <SCPDURL>/metainfoservice.xml</SCPDURL>
      </service>

      <service>
        <serviceType>urn:Belkin:service:remoteaccess:1</serviceType>
        <serviceId>urn:Belkin:serviceId:remoteaccess1</serviceId>
        <controlURL>/upnp/control/remoteaccess1</controlURL>
        <eventSubURL>/upnp/event/remoteaccess1</eventSubURL>
        <SCPDURL>/remoteaccess.xml</SCPDURL>
      </service>
.
      <service>
        <serviceType>urn:Belkin:service:deviceinfo:1</serviceType>
        <serviceId>urn:Belkin:serviceId:deviceinfo1</serviceId>
        <controlURL>/upnp/control/deviceinfo1</controlURL>
        <eventSubURL>/upnp/event/deviceinfo1</eventSubURL>
        <SCPDURL>/deviceinfoservice.xml</SCPDURL>
      </service>

    </serviceList>
   <presentationURL>/pluginpres.html</presentationURL>
</device>
</root>

Seem familiar? It’s the exact same response as when the official WeMo app requests /setup.xml (as shown in “Some Things Never Change: The WeMo Switch”). This seems logical and expected. The point of reiterating it here is to demonstrate that the SmartThings app is following the same protocol as the WeMo app to interoperate with the WeMo Switch, which is a third-party device.

The SmartThings app can be used to create custom triggers, as shown in Figure 4-19. In this case, the lamp connected to the WeMo Switch will turn on every time the door to which a SmartThings Multi Sensor is attached is opened. The lamp will then turn off after five minutes of no activity.

aiot 0419
Figure 4-19. SmartThings app controlling the WeMo Switch

Once set up, the SmartThings Hub can connect directly to the Switch and issue commands. For example, the Hub can send the following request to the Switch:

POST /upnp/control/basicevent1 HTTP/1.1
SOAPACTION: "urn:Belkin:service:basicevent:1#GetBinaryState"
Content-Length: 277
Content-Type: text/xml; charset="utf-8"
HOST: 192.168.2.10:49153
User-Agent: CyberGarage-HTTP/1.0

<?xml version="1.0" encoding="utf-8"?>
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/"
s:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
<s:Body>
<u:GetBinaryState xmlns:u="urn:Belkin:service:basicevent:1">
</u:GetBinaryState>
</s:Body>
</s:Envelope>

The GetBinaryState request’s intention is to query if the Switch is on or off. The Switch responds:

HTTP/1.1 200 OK
CONTENT-LENGTH: 285
CONTENT-TYPE: text/xml; charset="utf-8"
DATE: Mon, 20 Oct 2014 16:33:36 GMT
EXT:
SERVER: Unspecified, UPnP/1.0, Unspecified
X-User-Agent: redsonic

<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/"
s:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"><s:Body>
<u:GetBinaryStateResponse xmlns:u="urn:Belkin:service:basicevent:1">
<BinaryState>0</BinaryState>
</u:GetBinaryStateResponse>
</s:Body> </s:Envelope>

The value of 0 for BinaryState indicates that the Switch is turned off. As shown in Chapter 3, the Hub can also send a SetBinaryState request to toggle the power on.

Notice that, just like with the official WeMo app, no authentication or authorization is required. In order to interoperate with other devices such as the WeMo Switch and hue lighting, the SmartThings Hub and app have no choice but to follow the protocols defined by the third-party devices they are integrating with.

There is little SmartThings can do to secure the designs crafted by third-party devices it wants to integrate with. The toss-up is between accepting the risk and insecurity inherent in interoperability, or choosing not to integrate. It appears that SmartThings has decided to go the route of interoperability, aiming to be able to support a wide ecosystem of IoT devices (including those by third parties) that can in turn be programmed using the SmartThings app and IDE. This approach makes sound business sense, because it positions SmartThings to be the hub of IoT devices of the future. However, the risk that is exposed is the sum total of the impact of all insecure devices that SmartThings decides to interoperate with.

Conclusion

Companies like SmartThings are clearly enabling IoT in the home and helping us push toward a digital future that blurs the lines between our physical spaces and our online virtual spaces. The SmartThings IDE is a powerful way to elegantly program both these spaces to maximize benefit from IoT devices in our homes.

The majority of popular use cases, such as an event triggered by a door opening or a motion sensor detecting activity in the middle of the night, are clearly aligned toward protecting our safety. In cases in which our physical safety is the paramount issue of concern, it becomes extremely important that the technology supporting and enabling it be designed securely. In this chapter, we discussed why products like those offered by SmartThings need to enable authentication that goes beyond the traditional username and password approach. We’ve learned the hard way why a mere password is not enough to protect our online accounts, and we can’t risk doing the same with devices that are put in place to ensure our physical safety.

A popular concern with IoT devices is the ability to issue security patches to fix known security flaws. Security researchers have pointed out a major weakness in the SmartThings Hub that can lead to a man-in-the-middle attack, which was duly patched by SmartThings. This is a good example of IoT device manufacturers doing the right thing, by communicating with security researchers and diligently issuing firmware updates to their customers to remedy the issues that are identified.

We also studied how the powerful SmartThings developer IDE can be tied with traditional technologies, such as text messaging, and how this can be abused to spoof messages to users to scare them or to distract them. As we enable further IoT sensors in the home, we ought to think through all the various avenues of notifications and communications and have a strategy for gradually retiring traditional mechanisms such as text messaging. Such an approach might have to be more gradual than we’d like, given spotty data coverage in some areas. However, it is important that we begin to have the discussion now and educate users on the current shortcomings.

Unlike the Philips hue lighting system and the WeMo suite of products, the SmartThings Hub and devices do not connect directly. Instead, they connect to an external cloud infrastructure and exchange instructions. The SmartThings architecture is therefore less likely to fall victim to another rogue device on the same local network, because there is no implicit trust of local devices.

Given the frequency of successful phishing attempts and workstation compromise due to malware, this is a welcome design decision, because it keeps the SmartThings devices from falling prey to other infected machines on the same network. However, the SmartThings approach to this design does not stem from a conscious intent to be secure, but rather is more of a side effect of going to market with dependability on the cloud as the first step:

We made the decision at SmartThings to support a “Cloud First” approach for our platform. This means that in our initial release, there is a dependency on the Cloud. SmartApps run in the SmartThings Cloud, so for everything to work, your hub does need to be online and connected to our cloud. This will generally be the case, even when we implement hub-local capabilities as described below.

We believe in a “connected” service where local capabilities in the hub are meant to improve performance and insulate the customer from intermittent internet outages. We do not plan to support a perpetually disconnected mode.

We made the decision to limit SmartApps to the Cloud in our first release because it allowed us to focus on the experience of writing the applications and less on the mechanics of deploying that logic locally to the hub.

That said, we are actively considering implementation scenarios whereby we can distribute SmartApps to—and execute SmartApps locally on—the SmartThings Hub.

In all cases, we recognize the critical scenarios where a loss of communications with the SmartThings Cloud could have a degrading impact on critical, local use cases, and are being deeply thoughtful on how we minimize the risk of disruption.

We hope that SmartThings and other influential IoT device manufacturers continue to make efforts to design local and disconnected capabilities securely. Their recognition of the risk of critical scenarios arising from a loss of communications is laudable, and they are taking the right approach. However, we’ve seen in previous chapters how reliance on the local network as inherently secure can lead to a high probability of disruption and compromise of our privacy and security. As we look into the future, we ought to demand secure design as an intention, not a side effect. It would be a shame if the architecture designed to support critical functionality in times of a communication disruption were vulnerable to attacks when the communication channel is available.

Companies like SmartThings are leading innovation that will help us enable the IoT in our homes. We are also going to increasingly depend upon these devices for our well-being and for our safety. IoT device manufacturers and consumers ought to think more carefully about secure authentication, trustworthiness of communications, and secure interoperability among devices.

Get Abusing the Internet of Things now with the O’Reilly learning platform.

O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.