0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Android・家庭用ルーターのスキャンに対応してみた

0
Posted at

はじめに

前回、AI エージェントに自分の PC を読み取り専用で点検させる MCP サーバーを紹介しました。

その後、点検できる対象を PC から Android 端末と家庭用ルーターに広げ、名前も Personal Device Scanner MCP に変えました。
スキャン履歴とダッシュボードも加え、npm から npx で起動できるようにしています。

npx -y personal-device-scanner-mcp@0.5.2 setup

この記事では、追加した機能と、作る中でつまずいた点を紹介します。

前回と同じく、「安全である」と判定するツールではありません。所見が0件でも、検査範囲の不足や、公表されていない脆弱性の
可能性があります。最終判断は機器の所有者が行う前提です。

追加した機能

MCPツール / CLI 対象 内容
collect_android / check_android_monitoring_apps Android 端末 USB でつないだ自分の端末を adb で読み取り、既知の監視アプリ(ストーカーウェア)と照合
check_router 家庭用ルーター ルーターに一切アクセスせず、所有者が書いた機種・バージョン・設定を公表情報と照合
history(CLI のみ) すべて スキャンごとの要約を PC に記録し、表で表示
dashboard(CLI のみ) すべて 履歴を1つの HTML ページにして開く

旧パッケージ名 personal-pc-scanner-mcp は npm から削除し、新しい personal-device-scanner-mcp に移りました。
旧リポジトリの URL は新しい URL に転送されます。

Android 端末:USB でつないだ自分の端末だけ

PC に USB でつないだ自分の Android 端末を、adb の固定コマンドで読み取ります。端末への書き込みやアプリの削除はしません。

  • device:Android のバージョンとセキュリティパッチの日付
  • apps:利用者が入れたアプリと、端末が記録している導入元
  • privileged_access:ユーザー補助・通知へのアクセス・端末管理を持つアプリ(ストーカーウェアがよく悪用する権限)
  • 全パッケージを、Echap の stalkerware-indicators(CC-BY 4.0)と照合

Wi-Fi 経由の adb は点検しない

adb は Wi-Fi 経由(ワイヤレスデバッグ)でもつながります。
意図しない端末を点検しないよう、USB でつながっていると確かめられた端末だけを対象にしました。

シリアル番号の形(192.168...:5555 など)から推測するのではなく、adb track-devices --proto-text が返す
connection_type: USB を読んで判定します。エミュレーターで試すと SOCKET になり、正しく拒否されました。

USB デバッグを有効にすると、端末の攻撃面が増えます。README では「点検のときだけ有効にし、終わったら無効にして、
USB デバッグの承認を取り消す」よう案内しています。

家庭用ルーター:ルーターに触らずに点検する

ルーターの点検というと、ポートスキャンや脆弱性スキャンを思い浮かべるかもしれません。しかしそれはルーターに想定外の影響を
与えうるうえ、調査と攻撃の境目があいまいになります。そこで、ルーターには一切アクセスしない設計にしました。

所有者が、管理画面で確かめた機種・ファームウェアのバージョンと設定を設定ファイルに書くと、次と照合します。

  • JVN iPedia(IPA の MyJVN API):国内メーカーの脆弱性情報。所有者が router.jvn_lookup を有効にしたときだけ問い合わせ、
    送るのは機種の CPE 名だけです
  • CISA KEV:悪用が確認された脆弱性の一覧(CC0)。所有者がダウンロードしたファイルを読みます
  • 設定:初期パスワードの変更・自動更新・遠隔管理・VPN・UPnP・WPS・Wi-Fi の暗号化などを、警察庁・総務省・NOTICE の推奨と照らし合わせます。
    回答のない項目は「問題なし」ではなく「未確認」にします

ここからは、作る中で見つけた落とし穴です。どれもレビューや受入試験で見つかり、実データで再現してから直しました。

1. MyJVN は、日付を指定しないと「過去1週間」だけを検索する

MyJVN API の脆弱性一覧(getVulnOverviewList)は、発見日・更新日・発行日のパラメーターを省くと、それぞれ既定の
「過去1週間」で絞ります(公式 FAQ に記載)。

ある国内メーカーの機種で試すと、日付を省いた場合は 0件、3つとも「範囲指定なし(n)」にした場合は 2件
(2017年と2026年の公表)でした。古いまま修正されていない脆弱性ほど漏れるので、毎回3つとも n を付けています。

rangeDatePublic=n&rangeDatePublished=n&rangeDateFirstPublished=n

1回の応答は最大50件なので、totalRes(総数)に達するまでページを進めます。上限や期限で打ち切ったら、
取得できなかった件数と理由を返して partial にし、取得できなかった分を「該当しない」とは数えません。

2. 1つの脆弱性情報に、別の機種の範囲が並ぶ

1つの脆弱性情報に複数の機種が載り、機種ごとに影響を受けるバージョンが違うことがあります(例:機種Aは「Ver.1.71より前」、機種Bは
「Ver.2.55より前」)。別の機種の範囲で比べると、誤って「該当しない」になります。

そこで、所有者が登録した機種の CPE と一致する項目だけで比べます。ただし JVN では、同じ機種でも CPE の種別が h:(ハードウェア)と
o:(OS)で混在していたため、種別は区別せず、メーカーと製品名の部分の完全一致で照合しています。

3. 「2.6」と「2.55」はどちらが新しいか

影響を受けるバージョンは「ファームウェア Ver.2.55より前のバージョン」のような自由記述です。決まった形だけを読み取って比べますが、
**「2.6」と「2.55」**の比較で迷いました。

  • バージョン番号として比べると、6 < 55 なので 2.6 のほうが古い
  • 小数として比べると、0.6 > 0.55 なので 2.6 のほうが新しい

どちらが正しいかはメーカーの番号の付け方次第です。そこで、2つの比べ方の結果が食い違うときは判定せず、記述を添えて
unknown にしました(「1.07」と「1.7」も同じ)。誤って「該当しない」と言うより、確認を促すほうを選んでいます。

4. 「DIR-85」が「DIR-859」に一致してしまう

KEV にはバージョンがなく、製品名も自由記述(例:「DIR-859 Router」「Multiple Routers」)です。最初は機種名を部分文字列で
照合していたため、受入試験で「DIR-85」を入れると「DIR-859」の項目が高い深刻度で出てしまいました。メーカー名だけの一致で、
NAS の項目(「Multiple NAS Devices」)が混じる問題も見つかりました。

今は、製品名を語に分け、連続する1〜4語と機種名が完全に一致したときだけ一致とし、メーカーだけの一致はルーター全般の項目に限っています。

スキャン履歴とダッシュボード

AI が何を実行したかを後から確認できるよう、スキャンごとの要約を PC に記録するようにしました。

TIME                 VIA  OPERATION      STATUS     FINDINGS    SECONDS  TARGET
2026-10-15 09:12:04  mcp  malware        completed  0              41.8  downloads
2026-10-15 09:13:30  cli  android_check  partial    1 (high 1)      6.2  phone
  • 記録するのは要約だけで、ファイル名・アプリ名・CVE などの所見そのものは残しません
  • 履歴を読む MCP ツールは作らず、AI からは読めません。所有者が history コマンドで見ます
  • dashboard で、履歴を1つの HTML ページにして開けます。スクリプトを動かさず、外部から何も読み込みません
    (Content Security Policy で自身のスタイルだけを許可)

Screenshot 2026-10-17 at 14.55.28.png

所見の詳細もページで見たい場合は、history.details = true で結果全体を残せます。ただし既定では無効です。
たとえばスマートフォンで監視アプリが見つかった記録は、この PC を使える人(監視アプリを入れた本人を含む)にも見られるためです。

Windows だけで起きたこと

CI では Windows / macOS / Linux でテストしています。
Windows でだけ失敗したものが3つあり、どれも実際の不具合(か、テストの不備)でした。

症状 原因
書き込みの失敗をまねたテストで、書きかけのファイルが残った os.open の後の open() が失敗すると、ディスクリプターが閉じられずに残る。Windows は開いたままのファイルを消せない(macOS / Linux は消せるので気づかない)。open(..., opener=...) にして Python に閉じさせた
古い詳細から消すはずが、新しいものを消した 詳細のファイル名は保存時刻で、Windows では時計の細かさが足りず、続けて保存すると同じ時刻になった。新しい名前の時刻を、既存の最新より必ず後にした
ソースを読むテストが失敗した テストが OS の既定の文字コード(cp1252)で .py を読み、日本語を含むファイルで失敗した。Python のソースは UTF-8 なので、テストを直した

制限事項

  • Android の実機(USB 接続)での確認はこれからです。今はエミュレーター(Android 10 と 16)で確かめています
  • ルーターの結果は、所有者が書いた機種・バージョン・設定に基づきます。照合できるのは公表された脆弱性だけで、KEV には国内メーカーがほとんど載っていません
  • 影響を受けるバージョンの記述が決まった形でない場合は unknown になり、メーカーの告知で確かめる必要があります
  • クラウドの AI に結果を渡すと、アプリ名やファイル名などが送信されます。送信範囲は所有者が決めてください

おわりに

前回は「選択肢を絞る」「受け取る文字列を疑う」「検査できたかを自分で確かめる」の3つを書きました。
今回はそれに、「触らずに確かめられるなら触らない」(ルーター)と「記録するなら、誰に見られるかを考える」(履歴)が加わりました。

ソースコードは MIT ライセンスで公開しています。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?