RabbitOS脱獄: 秘密ログとGPL違反が発覚
(da.vidbuchanan.co.uk)- Rabbit R1はAndroid 13 AOSP上でキオスクモードのように動作するアプリベースのデバイスで、ブートローダーのアンロックや内部ストレージの変更なしにrootシェルを取得するテザード脱獄が実装された
- 脱獄はMediaTekブートチェーンの検証をそのまま通過させ、検証済みの
bootイメージが実際に使われる直前に、USBで送り込んだカスタムイメージへメモリ上で置き換える方式 - R1はMediaTek MT6765、4GB DRAM、128GB eMMCを搭載し、
ro.boot.verifiedbootstateがgreenの状態でもTCP bind shell経由でuid=0(root)アクセスが可能だった - 内部ストレージのログには、GPS位置、WiFi名、周辺基地局ID、外部IP、RabbitバックエンドAPI用のユーザートークン、Rabbitの音声MP3と文字起こしが残されており、RabbitOS v0.8.112でログ記録の縮小と工場出荷時リセットのオプションが追加された
- Rabbit Inc.はLinuxカーネルに静的リンクされたhall-effectスクロールホイールおよび回転カメラモータードライバーのソースを公開しておらず、GPL2違反の状態にあり、7月22日時点で関連する問い合わせに応答していない
Rabbit R1分析の出発点
- Rabbit R1は批評家から低評価を受けており、中古市場では定価200ドルを下回る価格で未開封品が売られている
- RabbitOSは独自のローカルAIモデルではなく、Android 13 AOSP上でキオスクモードのように動作するアプリで、クラウドとはWebSocket上のJSON APIで通信する
- 以前報じられた露出APIキーはサーバー側ソースコードから流出したものとされ、デバイス内には保存されていなかった
- その後のアプリアップデートには商用難読化ツールが適用され、MagiskやFridaのような解析ツールの検出、およびR1デバイスかどうかを検証するロジックが含まれた
- 静的解析だけでは追跡が煩雑になったため、eBayでR1を£122で購入し、工場出荷時ファームウェアを可能な限りそのまま残した状態でランタイム解析を進めた
R1ハードウェアと基本的なセキュリティ状態
- R1はMediaTek MT6765 SoC、4GB DRAM、128GB eMMCストレージを使用している
- MT6765には2019年から知られているbootrom exploitの
kamakiriが存在する - 128GBストレージはローカル保存データがそれほど多くないデバイス特性を考えると珍しい選択に見える
- MT6765には2019年から知られているbootrom exploitの
- R1所有者たちは
mtkclientでブートローダーをunlockし、カスタムROMの書き込みやroot化が可能であることを確認していた - 分析目標はカスタムAndroidシステムイメージを載せることではなく、工場インストール済みファームウェアを可能な限り維持したまま中身を調べることだった
- ブートローダーをunlockしてMagiskを導入する方式にはいくつか問題がある
- OTA差分アップデートが壊れる可能性がある
- 現在の解析妨害コードに検出される可能性がある
- 将来のアップデートが
ro.boot.verifiedbootstateのような値を検査した場合に検出される可能性がある
- そのため、変更点を減らして解析妨害ロジックが検知できる表面を最小化しつつ、ローカルroot権限を得る方向が必要だった
MediaTekベースのブートチェーン
- ブートチェーンはMediaTekのロジックで構成され、出発点はCPUシリコンに固定されたbootromである
- bootromは基本的なハードウェア初期化の後、eMMC
boot0パーティションからPreloaderをSRAMに読み込む- Preloaderは署名されており、bootromが署名を検証する
- ただし、R1では実際には検証していない可能性があり、追加確認が必要
- PreloaderはDRAMを初期化し、eMMC GPTパーティションから3つのイメージをDRAMへ読み込む
tee: Arm Trusted Firmware, EL3gz: GenieZone Hypervisor, EL2lk: Little Kernel, EL1
- LKはAndroid Verified Boot 2.0と
dm-verityを実装している- ブートローダーがlocked状態なら、検証失敗時に起動を拒否する
- unlocked状態なら警告を表示し、orange state関連フラグを設定する
dm-verity検証が失敗すると、ブートローダーがunlocked状態でも起動しない
- 検証が通るとLKがLinuxカーネルを展開して起動し、カーネルがinitramfsの
/initを実行する - R1はA/Bパーティショニングを使用しているため、
bootはアクティブスロットに応じてboot_aまたはboot_bとなる - ブートローダーのlock/unlock状態は
seccfgGPTパーティションに保存されるseccfgはいくつかのフラグと暗号化されたハッシュで構成されるfrpパーティションの最後の1バイトはfastboot flashing unlockのようなブートローダーunlockの許可可否に関与する
carroot: ストレージに触れないテザード脱獄
- 信頼チェーンのroot of trustはCPU efuseに入った証明書ハッシュと、それを検証するbootromコードである
- MT6765には
kamakiribootrom exploitがあるが、R1ではexploitなしでもbromとPreloaderのUSB bootloader modeがunsigned DAイメージを受け取り、メモリ上で実行する - 独自のDA payloadを作成し、PreloaderがDRAMにロードするようにした
- 動作フローは次の通り
- USBでカスタムAndroid
bootイメージをDRAMへロードする - PreloaderがLKへジャンプする直前にフックを仕込む
- Preloaderへ戻して通常のブート処理を継続する
- Preloaderが
tee、gz、lkイメージをeMMCから読み込み、検証する - LK突入直前にフックが実行され、LK内に追加のフックとパッチを仕込む
- LKは元のeMMC上の
bootパーティションを読み込み、検証する bootイメージがAVBコードからLinux起動コード側へコピーされる瞬間、フックがUSBで送り込んだカスタムbootイメージへ置き換える- 画面にはカスタムメッセージも表示される
- USBでカスタムAndroid
- 要点は、検証対象データはそのまま検証させつつ、検証後に実際に使われる直前でパッチ済みデータへ置き換える点にある
- フラッシュストレージは一切変更せず、脱獄プロセス全体はメモリ内だけで進行する
- 再起動すればデバイスはクリーンな状態に戻る
- リバースエンジニアリングの過程で原状復帰しやすい
- カスタム
bootイメージにはflashable-android-rootkitを使用する- 既定の
/initバイナリを置き換え、最大権限のユーザー空間サービスであるpayloadを注入する - イメージパッチツール
magiskbootはMagiskプロジェクトから持ってきている - 一般的なLinuxで
magiskbootをビルド・実行するためにmagiskboot_buildを使用する
- 既定の
- payloadはシンプルなTCP bind shellである
- ステルス性の高い方式ではなく、Rabbitアプリに検出される可能性がある
- 必要であれば今後改善できる
WebSerialベースの脱獄ツールと実行結果
- MediaTekデバイスの操作にはmtkclientがすでに必要な機能を提供しているが、動作理解のためにPython USBクライアントを自作した
- その後、これをjs/WebSerialへ移植し、物理接続されたRabbit R1をWebページから脱獄できるようにした
- 脱獄名はrabbitのしゃれを反映してcarrootと名付けた
- 実験用ツールはr1_jailbreakで公開されている
- 起動後にTCP bind shellで接続した結果は次の通り
$ rlwrap nc 192.168.0.69 1337
# id
uid=0(root) gid=0(root) groups=0(root) context=u:r:rootkit:s0
# getprop ro.boot.verifiedbootstate
green
- システムはsecure boot状態を
greenと認識しながらも、root shellアクセスを許可していた rootkitSELinux domainはflashable-android-rootkitが設定する
分析に使ったデバイスインターフェースと参考資料
- R1のiFixit分解写真にはTXとRXと表示されたテストパッドが見え、これはUARTテストパッドである
- UARTはブートチェーン全体でデバッグログを提供する
- brom段階は115200 baud
- その後の段階は921600 baud
- 論理レベルは1.8Vで、解析機器では3.3Vでも損傷なく動作した
- Preloaderはvolume-upキーを押していないとUART loggingを無効化する
- R1にはvolume-upキーがないため、Preloaderをパッチしてこのチェックを無効化した
- パッチ済みPreloaderはbootromのUSB download modeで起動できる
- Linuxカーネルcommand lineには次のフラグをパッチしてUARTへカーネルログを出力した
earlycon console=ttyS1,921600
- このパッチ構成により、ブート全体のUARTログを収集した
- SIMスロット経由でアクセスできるresetボタンの横にあるテストパッドを、reset中にGNDへ落とすとbrom USB modeで起動できる
- 主な参考資料は次の通り
- bkerler/mtkclient: MediaTek brom/preloader/DAインターフェース操作コード
- cyrozap/mediatek-lte-baseband-re: ベースバンド中心の資料とハードウェア・ブートノート
- 吴港南/preloader运行流程--基于MT6765: MT6765関連のPreloader動作フロー資料
- ng-dst/flashable-android-rootkit, LuigiVampa92/unlocked-bootloader-backdoor-demo, topjohnwu/Magisk:
/init以降の段階とroot化関連資料 - RabbitHoleEscapeR1/r1_escape: R1向けカスタムROM書き込みツールと手順
内部ログで見つかった個人情報
- R1は内部ストレージの
Android/data/tech.rabbit.r1launcher.r1/files/logs/配下に、日付ごとのテキストログを残していた - 2024年7月7日時点でログディレクトリには複数日分の
.logファイルがあり、一部ファイルは数MB規模だった - ログには次のデータが含まれていた
- 正確なGPS位置
- WiFiネットワーク名
- SIMカードがなくても収集される周辺基地局ID
- インターネット向けIPアドレス
- RabbitバックエンドAPI認証に使われるユーザートークン
- Rabbitがユーザーに話したすべての内容のBase64エンコードMP3とテキスト文字起こし
- このデータのうちGPS位置と周辺基地局IDはRabbitサーバーにも送信される
- 問題は2つあった
- 意味のあるハードウェアセキュリティがないデバイスに、過度に詳細なデータをログ記録していたこと
- 一般ユーザーが工場出荷時リセットする手段がなく、ログが事実上恒久的に残っていたこと
- 中古取引が活発な状況では、販売・寄付・廃棄時に以前のユーザーのログが残る可能性があった
- RabbitOS v0.8.112はセキュリティアドバイザリを通じて、ログ記録を減らし、工場出荷時リセット用の設定オプションを追加した
- この対応は迅速に行われ、Rabbitがユーザープライバシーとセキュリティ問題に比較的先手で対応した初めての事例と評価された
AOSPカスタマイズの実際の範囲
- Rabbitは、RabbitOSが単なるアプリだという報道に対し、「lower level firmware modifications」を含む非常にカスタマイズされたAOSPだと説明したことがある
- 現時点で確認されたカスタマイズは主に、単一アプリのキオスクモードを維持するためにAndroid機能を削る方式である
- navigation barなし
- notification barなし
- ADB有効化を防ごうとする措置あり
Judyというアプリはバックグラウンドで実行され、ADBが動作中だと無効化する- 7月4日、@MarcelD505はWiFi captive portal loginブラウザを起点にAndroid system settingsアプリへ入るキオスク脱出方法を公開した
- Rabbitは最新アップデートでAndroid system settingsアプリをデバイスから完全に削除し、この経路を塞いだ
- これまでに確認された特注AOSP変更は、新機能を追加するより機能を削除する方向に近い
- 現在実装されているRabbitOSが、一般的なスマートフォンアプリでは不可能だと見なせる技術的理由はまだ確認されていない
一般のR1ユーザーが気にすべき点
- 意図せず脱獄された可能性が心配なら、電源を切って再度入れればよい
- 通常どおり警告メッセージなしで起動するなら、おおむね安全な可能性がある
- ただし、bromがeMMC上のunsigned Preloaderイメージを起動するよう設定されている場合は確実ではなく、追加テストが必要
- ベンダー提供の信頼できるstock firmwareイメージで再書き込みできればより望ましいが、Rabbitはその手段を提供していない
- R1を無人状態で放置すると、デバイスに保存されたデータが知識のある人に容易に抽出される可能性がある
- 販売・寄付・廃棄の前には、新たに追加された設定オプションで工場出荷時リセットを先に行うべきである
GPL違反と結論
- Rabbit R1はスクロールホイールと回転カメラを除けば、特殊なハードウェアではなく一般的なMediaTek Androidデバイスに近い
- AOSPカスタマイズの大半は、単一アプリのキオスクモードを強制するため既存機能を削る形である
- ブートチェーンのセキュリティは有効とは言えず、デバイスを安全に放置しにくい
- Rabbit Inc.はLinuxカーネルのGPL2ライセンスに違反している
- hall-effectスクロールホイール検出ドライバーがclosed-source状態である
- カメラ回転用stepper motor制御ドライバーもclosed-source状態である
- これら2つのドライバーはGPLカーネルイメージに静的リンクされている
- 7月12日にRabbit Inc.へ本文に関するコメントとGPL遵守計画を問い合わせたが、7月22日時点で返答はなかった
- 公開されたテザード脱獄ツールは、研究者が自分の所有するR1へアクセスし、今後パワーユーザーがデバイス機能を拡張する助けとするための実験的ツールである
1件のコメント
Hacker Newsの意見
GPLでは求められた際にライセンスとソースコードを公開しなければならないが、Truth SocialはAGPLコードを使っていたことが明らかになるまでライセンスすら公開せずにやり過ごし、その時になってようやくソースを公開した
Rabbitも同じように切り抜けるのか気になる
実際には権利者が知らない違反を追跡することはできず、通常は損害賠償よりも違反者をコンプライアンス状態に戻すことに関心が向く
https://www.gnu.org/licenses/old-licenses/gpl-2.0.html
カーネルモジュールはカーネル本体の修正が不要なら、リンク方式に関係なくLinux側にGPL例外があるものだと思っていた
このログの内容はかなりひどい。正確なGPS位置、WiFiネットワーク名、SIMカードがなくても周辺基地局ID、外部に露出するIPアドレス、RabbitバックエンドAPI認証用のユーザートークン、さらにはRabbitがユーザーに話した内容すべてのBase64エンコードされたMP3とテキスト書き起こしまで入っている
「近くでおすすめのレストランは?」のような質問に答えるために作られた機器が、リクエストと一緒に位置コンテキストを送るのは驚くことではないが、何の理由もなく位置を流し続けているなら懸念すべき
WiFi名は再接続のために保存する必要があるし、ローカルログにIPアドレスが見えるのもそれほど不自然ではない
ユーザーアクセストークンも毎回ログインせずに再接続するには機器に保存せざるを得ない。ただしトークンをログにそのまま残すのは良くない慣行であり、そのログが当該DBや設定ファイルと同じ保存先にあるなら、それ自体でまったく新しい問題というわけでもない。ログをサーバーに即時アップロードしているなら、もちろん問題になる
こういう機器に滑らかで魔法のような動作を求めるなら、常に聞き、見て、位置を送る必要がある。実際にこれをちゃんと動かすにはローカル推論が必要で、5年後にAppleがはるかに良い版を作るであろうものに、なぜ今お金を払うのかは分からないが、あえて買うならこういう方式が必要
巨大企業は嫌いなのに、スタートアップがデータなしで良い製品を作ることを期待するわけにはいかない。Rabbitが将来もっと良いものを作る可能性を持つためにも、こうしたデータは必要
これが不快だと言うなら、なぜ不快なのかを具体的に説明すべきだ。大半はそれ自体として大きく心配するようなことではない
笑える。Rabbitで働いていたが、コードベースを読んで幹部にガスライティングされた末に辞めた
外から見える脱獄や脆弱性だけでも氷山の一角のように思える
Rabbitが返答していないのは、弁護士たちがどう訴えるか検討しているからだろう
実際に返答できる営業時間をほとんど与えていないことになる
RabbitOS開発者は、USB経由のブートローダーアクセスを防ぐようeFuseを設定することでこの問題を修正できる
Motoも数年前、MediaTek機器で同じブートROM攻撃面に脆弱だったときにこう対処した。記憶が正しければ、このeFuseはLK段階で設定され、通常の無線ファームウェアアップデートで適用された
記事はすばらしい
ソフトウェアはひどそうだし、会社も今のところあまり良く見えない
それでもキオスクモードだけでもカスタムアプリを簡単に動かせるなら、このフォームファクタでかなり面白い用途がありそう
PWAを雑に載せられるなら、ESP32とバッテリーと画面を自前で組み合わせて作るよりずっと速いし、かなり良い一体型デバイスに見える
理想を言えば、Googleサービス抜きでもっと安全に動かせるとよく、GrapheneOSのような方向性なら悪くない
まだ調べてはいないが、こういう単一目的のカスタムアプリに使っている事例や参考になる資料があるのか気になる
価格が50ドル未満に下がれば、たとえばサーバーが止められた後なら、その時は良いハードウェアプラットフォームだという意見に同意できる
この製品にはうまくいってほしかったので残念
今後のハードウェアユーザーインターフェース + AI実験にとって厄介な前例のように残らないでほしい。ガラスの長方形をタップしてスワイプするよりもっと良いやり方があるはずだというBret Victor的な考えには、今でも共感する
もっと手軽に、スマートウォッチが問い合わせを携帯電話に中継することもできる
Humaneは実際の問題を解決していないように見えても、本当に別のことを試した点はある程度評価する。Rabbit R1はただの安物のガラクタだ
Rabbitに対する初期の好感の全部、あるいは大部分がTeenage Engineeringのデザインによるものだったというのは少し笑える
TEには今後もっとクライアントを選んでほしい。Rabbitの背後にいる人物は札付きの詐欺師だ
名前を検索すればいいのだろうが、最近は検索品質がひどすぎるのでやる気がしない。批判をもっと詳しく示すリンクがあれば助かる
これはAIアシスタント界のJuiceroみたいだ
ただ、会社専用のあらかじめカットされた果物ミックスの袋を絞る機械に、人々が法外なお金を払うと思い込んでいただけだ。すべては意図どおり正確に機能していて、実際のビジネスモデルがばかげていただけだった
Mycroft(https://en.wikipedia.org/wiki/Mycroft_(software))とLeon(https://getleon.ai)を合わせたような、プライバシーを保護するオープンソースAIアシスタントを期待していた