概要
Tapoカメラのセットアップに苦戦し、独自にオンボーディングフローを解析。 APKのデコンパイルやTLSセッションのMITMによる通信解析を実施。 デフォルトパスワードの特定とAPI暗号化の仕組みを解明。 Pythonスクリプトで通信内容の復号・解析を自動化。 最終的にクラウド不要なセットアップスクリプトを作成し、カメラの仕組みを詳細に把握。
Tapoカメラ逆解析の経緯
- Tapo室内カメラ を安価に購入し、外出時の犬の行動確認を目的とした導入。
- Frigateへの組み込み が困難で、オンライン情報も乏しく設定に苦戦。
- 2way音声対応 にはrtsp://ではなくtapo:// go2rtc構成が必須という独自仕様。
- TP-Link独自API でのみ2way音声を実装しているため、標準プロトコル非対応。
- オンボーディング後に クラウドパスワード変更 しても、デバイス側は同期されない挙動を確認。
- デバイスAPIは admin:<Tapoクラウドパスワード> で認証するが、パスワード変更後も古い情報のまま運用される仕様。
オンボーディングの仕組み推測
- 初期セットアップ時に クラウドパスワード同期APIコール が存在。
- 同期以前は 未認証またはデフォルトパスワード でアクセス可能。
- Tapo Careサブスクリプション の強制表示など、クラウドレス運用の必要性を痛感。
MITMによる通信解析
-
オンボーディング時の通信内容 を把握するため、アプリとカメラ間のMITM(中間者攻撃)を実施。
-
mitmproxy をPC上で起動し、 Frida でアプリの証明書ピンニング回避を実装。
-
スマホの全HTTPS通信をプロキシ経由で記録・解析する環境を構築。
- 通信フロー:
- Tapo App(Frida hooks)→ Laptop(mitmproxy)→ Tapo Camera
- リクエスト・レスポンスの全記録と転送
- 通信フロー:
通信内容の解析結果
- 初回ログイン時、 adminユーザーでパスワード未設定 の状態を確認。
- 以降のAPI通信は securePassthrough による暗号化ペイロードでやりとり。
- Tapoカメラはデフォルトパスワード を持ち、クラウド同期前に完全ログイン可能。
- API通信の暗号化 で外部解析を防止。
APKデコンパイルとパスワード特定
- JADXでAPKを解析 し、"admin"文字列を検索。
- CameraOnboardingViewModelクラス 内でパスワード生成ロジックを発見。
- encrypt_type: 3 の場合、デフォルトパスワードは TPL075526460603 であると特定。
mitmproxy用スクリプト開発
- デフォルトパスワード判明後、 セッションキー導出・API復号化 が可能に。
- PyTapo をリファレンスに、mitmproxy上で復号スクリプト(tapo_decrypt_pretty.py)を作成。
- ログインハンドシェイク(cnonce, nonce, device_confirm)監視
- セッションキー自動生成・API復号化
- mitmproxy UI上で平文表示・JSON保存
オンボーディングAPIコールの全貌
- 主なAPIコール一覧:
- scanApList(Wi-Fi一覧取得)
- setAccountEnabled / changeThirdAccount(RTSP/ONVIFアカウント有効化)
- changeAdminPassword(パスワード変更)
- connectAp(Wi-Fi接続)
- その他:タイムゾーン設定、クラウドバインド、記録プラン等は本質的でない付帯機能。
クラウドレスセットアップ自動化
- Bashスクリプト(tapo_onboard.sh)で以下を自動化:
- デフォルトadminパスワードでログイン
- Wi-Fiアクセスポイント選択・接続
- OSDロゴ非表示化
- RTSP/ONVIF有効化
- パスワード変更
- Wi-Fi接続完了
Tapoファームウェアの所感
- APIエンドポイントごとに SHA-256とMD5が混在 し、暗号化仕様が統一されていない。
- パスワード送信用の公開鍵が 2種類存在 し、どちらを使うかは不明確。
- アプリとデバイス間のパスワード同期 は一貫性に欠け、仕様が曖昧。
- 全体的に 暗号実装の品質が低く、コスト重視の設計を感じさせる。
- 価格相応の品質だが、 最終的にはクラウドレス運用を確立。
犬の行動観察の結末
- 解析作業の末、 犬はソファやベッドで寝ているだけ という事実に到達。