2 ポイント 投稿者 GN⁺ 2024-07-02 | 1件のコメント | WhatsAppで共有
  • Sleep Number HubでUARTコンソールとU-Boot環境変数を使ってrootアクセスを取得すると、SleepIQサーバーを経由しないローカル制御経路を構築できる
  • 既存のHomebridgeプラグインはSleepIQ APIを5秒ごとに呼び出しており、数千人規模のユーザー環境ではSleep Numberネットワークに負荷をかけたため、無効化を要請された
  • 対象機器はSleep Number Hub 360SIQ01Dで、J16 UARTピン、115200 baudコンソール、FAT32またはExt3のUSBドライブ、SSH公開鍵の登録が重要な条件となる
  • rootアクセス後はHubのPython 2.7.18/bam/scriptsを活用し、ポート8000のHTTPサーバー経由でベッド設定と状態をローカルネットワーク上で扱える
  • HubはSleep Numberサーバーに対してSSHリバーストンネルを開けるため、ローカル制御が十分に整ったら外部インターネット接続を切り、Bluetoothや内部制御を使うほうが安全である

ローカルアクセスを探すことになったきっかけ

  • 目標はSleepIQサーバーを経由せず、Sleep Numberベッドをローカルネットワークで制御することだった
  • 以前に作成したhomebridgeプラグインでは、HomeKitや自動化からベッド設定を制御できた
    • 特に人がベッドにいるかを示すbed presenceの値は、照明を消す、ドアを施錠するといった自動化に役立った
  • このプラグインはSleepIQ APIを5秒ごとに呼び出しており、ユーザー数が数千人に増えるにつれてSleep Numberネットワークに負荷を与えた
    • Sleep Numberはプラグインの無効化を要請した
    • リポジトリのブランディングが公式Sleep Numberツールのように見える可能性があるという問題もあった
  • その後、既存の作業は新しいhomebridge-bed-controlプラグインへと引き継がれた
    • 新しいプラグインではbed presence監視をデフォルトで無効化し、有効化前に警告を追加している

Hubハードウェアで見つけたアクセス経路

  • 当初はCPU近くのJ10ヘッダーを調べたが、UARTデータは得られなかった
    • そのCPU構成ではUARTラインが出ていない状態だった
  • 基板下側のJ16ヘッダーでUART信号を探すため、ロジックアナライザを10本のヘッダーピンに接続した
  • UART-TTYデバイスを接続すると、デバイスコンソールにアクセスできた
  • フラッシュをダンプしてファイルシステムや脆弱性を調べたが、UARTなしで誰でもログインできるバックドアは見つからなかった
  • その代わり、Sleep NumberがHubへSSH接続できる保守用バックドアを発見した
    • Hubは内部ホームネットワークに接続されているため、このアクセス経路は内部ネットワークへつながり得る
    • Wi-Fi接続を切り、可能な限りBluetooth制御を使う運用が推奨される

準備物と対象機器

  • 手順はSleep Number Hub 360SIQ01Dモデルで実施された
  • 必要な機材はUART-TTYデバイスと基板接続用ツールである
    • USB-C to UARTまたはUSB-A to UART
    • Raspberry Pi Pico WはSSHが動作しない場合のリモートコンソール接続用として内部に恒久設置できる
    • 2.54mmピンヘッダーとハンダごて、またはPCBクリップクランプ
  • 基板と通信するにはシリアルコンソールが必要
    • LinuxとMacではminicomが使える
    • WindowsではPuTTYが使える
  • USB-AフラッシュドライブはFAT32またはExt3形式でなければならない
  • 使用中のHubにすでにUSBデバイスが挿さっている場合、それはWi-Fiドングルの可能性があり、このデバイスがないとブートループが発生することがある

rootアクセス手順の要点

  • UARTデバイスは基板のJ16ヘッダーに接続する
    • pin 1: TX、Hubへ入る信号
    • pin 2: RX、Hubから出る信号
    • pin 3: ground
  • シリアルコンソールは115200 baudに設定する
  • Hubの電源投入後2秒以内にSpaceキーを押し、自動起動を停止する
  • U-Boot環境変数はまずprintenv -aでバックアップしておく必要がある
    • デフォルト値への復旧が必要になる場合があるため、現在の環境との差分を記録しておくべきである
  • bootcmdではrun set_bootargs;の部分を削除し、ブート引数を手動で設定できるようにする
  • /initスクリプトはハッシュ化されたbootrom内にあり直接修正できないため、bootargsで実行時に/initの内容を変更する
    • デフォルトのスクリプトはlet_me_rootという文言で復号される暗号化ファイルを探す
    • 復号処理の行を復号後の値に置き換えることで、暗号化ファイルの要件を回避する
  • 最初の起動時にはlet_me_rootファイルを含むUSBドライブが必要
    • 起動後にコンソールでroot@bam-se:~#プロンプトが表示されれば、rootシェルに入れている状態である
  • その後はrootパーティションを読み書き可能で再マウントし、/root/let_me_rootファイルを作成して、USBなしでもアクセスを維持できるようにする

SSHアクセスの設定

  • rootプロンプト取得後は、SSH公開鍵/root/.ssh/authorized_keysに追加してネットワーク接続を設定する
  • 接続元のローカルマシンでSSH鍵を生成する必要がある
    • 例のコマンドはssh-keygen -t ed25519
    • 説明文ではecdsa鍵を推奨しているが、実際の例ではed25519を使っている
  • 公開鍵追加後はssh root@$hub_ip -i <path to id_ed25519>の形で接続をテストする
  • 接続できない場合はauthorized_keysの形式とファイル内容を確認する必要がある
    • そのファイルには2つの鍵があるべきだとされている

ローカルネットワーク制御サーバーの構築

  • rootアクセスだけではベッドアプリの制御機能を置き換えにくいため、Hub内でローカルHTTPサーバーを起動する
  • HubにはPython 2.7.18が含まれている
    • Hubの最終更新は2018年に見える
    • Python 2.7.18には必要な機能を提供するsimpleHTTPServerパッケージがある
  • script_server.pyはポート8000でHTTPサーバーを開き、/bam/scripts内のスクリプトを実行する
    • URLパスがスクリプト名になる
    • argクエリパラメータを複数渡してスクリプト引数として使える
    • 実行結果はブラウザに表示される
  • スクリプトはscp -O script_server.py root@$hub_ip:~の形でHubへコピーする
  • 再起動後に自動起動させるには、起動スクリプトに追記するかrc.dスクリプトを追加する必要がある

再起動後の自動実行設定

  • 実行中のOSインスタンスは、bootloaderの/initスクリプトが作成したchroot内で動作している
  • 多くのシステムファイルはtmpfsパーティションに保存されており、直接修正しても再起動後には保持されない
  • 元ファイルがあるディスクパーティションを別途マウントすれば、再起動後にコピーされる元の/etcファイルを修正できる
  • script_server.sh形式のinitスクリプトを作成してHubへコピーし、元のrootパーティションのtmp/etc/init.dに配置する
  • rc0.drc3.drc4.drc5.drc6.dにシンボリックリンクを追加し、起動時と終了時に実行されるよう設定する
  • 再起動後にブラウザでhttp://$hub_ip:8000/bamstatへアクセスしてHubの状態情報が見えれば、サーバーは正常に動作している

/bioスクリプトで可能な制御

  • /bioはベッドの主要な制御スクリプトと思われる
  • コマンドは/bio?arg=XXXX形式で渡す
  • Sleep Number値の取得と設定が可能
    • PSNL, PSNR: 左右ベッド側の最後の設定値を取得
    • PSNl, PSNr: 左右ベッド側の現在値を取得
    • PSNX: 両側の最後の設定値と現在値を取得
    • PSNS&arg=L100: 左側のSleep Number値を100に設定、値の範囲は5..100
  • 在床検知とプライバシー設定も扱える
    • SPAU: プライバシー設定を取得
    • SPAU&arg=on: プライバシー設定を有効化、offで無効化
    • LBPL, LBPR, LBPX: 左側、右側、両側の在床値を取得
  • Responsive Air、ベッド位置、照明、足元加温機能も含まれる
    • LRSG: 両側のResponsive Air設定を取得
    • LRLE&arg=on, LRRE&arg=off: 左右のResponsive Air設定を変更
    • MFST: 頭部と足部の位置を取得
    • MFUL, MFUR, MFFL, MFFR: 左右の頭部・足部位置を設定
    • MFO3, MFSO: アンダーベッド照明またはコンセントの状態と明るさ・タイマーを設定
    • FWGL, FWGR, FWSL, FWSR: 左右の足元ヒーターのレベルとタイマーを取得・設定
    • SBAS: ベッド基準値を設定
  • /bio?arg=helpは実行可能なコマンド一覧を表示する
    • help呼び出しの第2引数としてコマンドを追加すると、そのコマンドの詳細情報が表示される
  • bioスクリプトにはfoundation preset、いびき設定、DualTemp制御、状態情報も含まれる
    • factory resetやradio制御のような破壊的コマンドには注意が必要
    • 筆者が使用したbioバージョンではMFSO項目の順序がLIST内で誤っており、呼び出すには数行上へ移動する必要があった

アクセス後に調べられる領域とセキュリティ上の懸念

  • ベッド制御機能は/bamルートディレクトリに集約されている
    • この中の各種スクリプトを見れば、Hubがどのように動作しているかを確認できる
  • UARTなしでアクセス可能なバックドアを探そうとしたが、明確なアクセス経路は閉じられていた
  • HubはSleep Numberサーバーと通信する際にSSHトンネルを開き、開発者が保守に使えるリバーストンネルを提供している
  • 外部利用者が内部ホームネットワークへ直接接続できる可能性があるため、内部ネットワーク制御スクリプトが十分に整ったらHubの外部インターネット接続を切る方法を検討している
  • SleepIQアプリを直接置き換えられるシンプルなProgressive Web Appも次の段階の候補である

1件のコメント

 
GN⁺ 2024-07-02
Hacker News のコメント
  • かなりばかげている。昔こういうベッドを使っていたが、すべてがスマートになる前の話だった。ポンプには有線コントローラーが2つ接続されていて、コントローラーには数字表示と上下の調整ボタンがあった。
    インターネットも不要、Linux ベースのマイクロコントローラーも不要、ベッドがハックされることもなく、快適に眠れた。

    • 「これはとんでもない過剰な複雑さだ」と感じるたびに、それが誰かの生活をどれほどシンプルにできるか想像してみるようにしている。
      たとえばパーキンソン病から四肢麻痺まで、何らかの運動障害があるなら、音声や標準化された入力方式で動作する共通コントローラーにつながることは大きな利点になり得る。製品ごとにばらばらなアクセシビリティ上の制約に個別に対処しなくて済むからだ。
      体に不自由のない人にはスマートホーム機器の大半がほとんど役に立たないように見えるが、別の人にとっては命綱になり得る。
    • こういうベッドなら買う。ベッドにまでWi‑Fi 接続機能を付ける必要があるというのは変だ。ただ壁のコンセントに挿すだけよりハードウェアが余計に必要になるわけで、狂っていると思う。
  • 「ハブが Sleep Number のサーバーと通信するときに SSH トンネルを開き、開発者が必要なときにハブへ接続してメンテナンスできるようリバーストンネルを提供する」という部分が気になる。
    公開鍵認証を使っているのかパスワードなのか、家へトンネルするときに IP を使うのか DNS を使うのか見てみたい。条件がぴったり揃えば、人類史上いちばん笑えるDNS ハイジャック構成が可能になりそうだ。
    Homer Simpson の不朽の表現を借りれば、ベッドが上がり、ベッドが下がる。

    • 旧式: 暗号資産保有者を狙うSIM スワッピング攻撃
      新式: Sleep Number のベッドは注文情報とひも付いているので、Sleep Number に侵入して標的を見つけ、その人のベッドに SSH で接続し、家庭内ネットワークへピボットして暗号資産ウォレットを盗む。
      どうせお金はいつもマットレスの下に隠すものだから ;)
    • 購入前にその事実を知らされていなかったのなら、ベッドの所有者は訴えるべきでは? ネットワークへ無断アクセスしてバックドアを仕込むのは犯罪ではないのか?
  • ベッドがなぜ Linux を動かす必要がある? なぜ?
    あり得るすべての時間線の中で、いちばん間抜けな場所に生きている気がする。1GB RAM と完全な OS が入っていない普通のベッドの何が問題だったのか。どこも同じだ。Wi‑Fi に接続しない洗濯機を探すのも一苦労だったし、10年後にまたそれをやることを考えるとぞっとする。
    趣味であれ金稼ぎであれ、O(1000) 個くらいの「スマート」機器を破ってきた立場からすると、こういう物を家に入れたくない。だがこうしたLinux 駆動ベッドのような狂気のせいで、避けるのがどんどん難しくなっている。頼むからやめてほしい。

    • ベッドは複雑である必要はない。昔はZ80 と 32K RAMだけで、ベッドでやるべきことは全部できた。初めて協調的マルチタスク対応ベッドを買った日は本当に記念碑的だったし、高密度の布団はゲームチェンジャーだった。
      ただ、空のビニールレコードを持って公共図書館まで行き、ソフトウェア更新を受け取っていたことは懐かしくない。うっかりするとトコジラミが出たからだ。
    • https://imgur.com/6wbgy2L
      「自分が持っている最新のテック製品は2004年製のプリンターで、予期しない音を出したら即撃つために装填済みの銃を用意している」
    • ベッドが Linux を動かす理由は、よりよい結果のために自分自身を測定する時代に生きているからだ。
      1世紀前には抗生物質を見つけ、それは大きな前進だった。その後、明確な病気と明確な治療法をたくさん見つけ、今は複雑で微妙なものが残っている。このベッドは睡眠状態を知らせるために Linux を動かしている。
      よく眠れないと、一般に弱いながらもさまざまな悪影響が出るし、それを知れば改善できる。毎晩低強度の睡眠検査をしてくれるようなものなので、価値ある情報になり得る。
      Sleep Number のベッドは数千ドルするので、避けようと思えば十分避けられると思う。
    • 自分も同じ感覚だ。幸いなのは、この流れのおかげで、より古く中古で修理可能な物をずっと安く買うようになり、古い電子機器のちょっとした修理も少しずつ覚えるようになったことだ。
      財布にも大きな得だし、まだ使える物を埋立地へ送らずに済む満足感も大きい。減らす、再利用する、リサイクルする、というのは重要度の順そのものだ。
    • 少なくとも Windows は動かしていない。
  • 最初はこの記事を、法的な理由で会社名を直接言いたくない人が Eight Sleep のベッドのハックを扱ったものだと完全に思い込んでいた。
    ところが実在するらしい「Number Sleep Hub」の写真を見て頭がおかしくなった。水冷ベッドを作る会社が2社もあり、片方が Eight Sleep、もう片方が Sleep Number だなんて、この時間線はあまりにも変だ。このインスタンスの乱数生成器が悪いシードを受け取った感じがする。

    • Sleep Number という名前は、マットレスの硬さ調整値に由来する。自分の「sleep number」を選び、パートナーはベッドの反対側で自分の値を選ぶ、という仕組みだ。
    • 笑える偶然だとは思うが、Eight Sleep は訴えられないギリギリのところでSleep Number と紛らわしい名前を選んだように見える。
    • Sleep Number ブランドはたぶん80年代からあったと思う。自分で使ったことはないが、古いブランドなのは確かだ。米国外にいるなら聞いたことがないかもしれない。
    • Sleep Number のベッドは基本的に、巨大なマットレス形の長方形の空気袋がフォームの墓場の中に入った構造だ。
      https://i.ytimg.com/vi/pMiTq6YkJ2c/maxresdefault.jpg
      人々は文字どおり、上にフォームが載った高級な調整式エアベッドに数千ドルを払っているわけだ。
    • どちらも初耳だったので、タイトルは「睡眠の質を改善するために脳の root 権限を得る方法」についての比喩だと思っていた。
      こういうベッドには、暗い場所でも手探りで使える物理コントロールがあってほしい。眠ろうとしている最中に調整するためスマホを顔の前に取り出さなければならないのなら、ベッドとマットレスのメーカーが睡眠の質に何が良くて何が悪いのか本当に分かっているのか疑わしい。
  • Eight Sleep Pod 3にも同じように入る方法がある [0]。一部のモデルには書き換え可能な MicroSD カードが入っているため、追加のハードウェアは少なくて済む
    本文の方法は、カードがない Pod で root 権限を得るには良い方法かもしれない。ただ、今知ったのは、Eight Sleep はファームウェア更新に署名しているものの、その更新に署名するために使う秘密鍵も同じパッケージで送ってくるという点
    [0]: https://github.com/bobobo1618/ninesleep

    • 皮肉なことに、これを見たらむしろ1つ欲しくなった。スマートデバイスをローカル化したり、Home Assistantで制御できるようにして、インターネット接続を切れるなら、そこまで悪くなさそう
      もちろん2,000〜4,000ドルは高いが、10年くらい使う一度きりの費用だと考えれば妥当ではある。でも4,000ドル払ったうえに月25ドルも払えというなら、あり得ない
  • Eight Sleep でも同じことをした人がいるのか気になる。インターネットが切れたという理由でベッドの温度を調整できないというのは、本当にかなり気に障る

    • これは何という新手の地獄なのか。なぜインターネットに接続する必要があるのか?
    • 自分の場合は毛布が95%を解決してくれて、スキー小屋では安い電気マットレスパッドが残りの5%を処理してくれる
    • Eight Sleep を買おうとしていたが、こういうことをしていると知ってすぐに興味が失せた。マットレスカバーに1,000ドル以上払うのに、物が動くようにするための「家賃」まで払うつもりはない
  • Sleep Number は買わない
    何年も空気注入式マットレスで寝ていたが、メーカーが中国に外注し始めた後、内部隔壁の縫い目が2つのマットレスで破れた

  • 「このガイドに従うと Sleep Number ハブの内部ファイルを変更する必要があり、保証が無効になる」みたいな戯言を広めるのはやめてほしい
    「剥がすと保証無効」ステッカーが法的に執行できないのと同じで、誤用や不十分なメンテナンス以外で製品保証を自動的に無効化するものはない
    スマートベッドが壊れたときにコントローラーをいじったという理由だけで、メーカーが保証義務から逃れられるわけではない。黙示保証も含まれる。消費者が製品を壊した、または「不合理な」方法で使った、あるいは適切にメンテナンスしていなかったことを立証する責任はメーカー側にある
    JTAG を接続しようとして、うっかり 5V を 3.3V のロジック回路にブリッジしてベッドの頭脳を焼いてしまったなら、それは自分の責任
    だが電源装置が吹っ飛んでコントローラーが故障したのなら、JTAG ヘッダーを付け、目玉シールを貼り、ピンク色に塗ったという事実は関係ない。修理すべきだ
    ファームウェアを変更していたとしても、その変更が故障の原因だとメーカーが立証しなければならない
    ノート PC でゲームをして発熱が多いからといって、保証が無効になるとは考えない。Firefox をインストールしても Linux をインストールしても同じだ。なのに、デバイスが少し「間抜け」だからといってルールが変わると考える理由はない

    • 紙の上の法律と現場の実際の法律は違う。メーカーが保証履行を拒否したら、顧客にできることはごく少ない
  • 次はランサムウェアだろう。「1,000ドル払わなければ、これから1か月お前のベッドで眠れなくしてやる」

    • 次はサブスクじゃないの?
  • いくつか事実を見てみよう
    Sleep Number のベッドには心拍数を検知するセンサーが入っている。エアマットレス内の圧力差を検知してそれを行う。実質的にはマイク同然で、かなり敏感だ

    • 本当に圧力センサーで心拍数を検知するのか? ノイズが多すぎてデータが使えなさそうだが
      調べてみると、かなりもっともらしい統計解析を組み合わせて、十分に正確なデータを得ているようだ。興味深い