Electronのセキュリティについて話すとき大抵話題になるのはXSSとnodeintegrationによる任意コード実行ですが、それだけ考えていればいいというわけではありません。
Electronのドキュメントでは最低限確認すべき事項をリスト化しており、BrowserWindow
やwebview
で外部のコンテンツを読み込む場合の注意点に一つ項目を追加したので紹介します。
-
Security, Native Capabilities, and Your Responsibility - Electron
- Use
ses.setPermissionRequestHandler()
in all sessions that load remote content (現時点ではmasterブランチにのみ記載)
- Use
Electronは許可の必要な動作をユーザーに確認しない
例えばカメラやマイクへのアクセス許可です。WebRTCに対応したブラウザで https://webrtc.github.io/samples/src/content/getusermedia/gum/ を開くと、getUserMedia()
の呼び出しのためにカメラへのアクセス許可を求められるはずです。そのためユーザーの許可なく外部コンテンツがカメラにアクセスすることはできません。
では、このページをElectronで開いてみましょう。何の確認もなく、いきなりカメラの映像が表示されると思います。
// 作成時点のバージョン: 1.4.15
const {app, BrowserWindow} = require('electron');
let win;
app.on('ready', () => {
win = new BrowserWindow({
webPreferences: { nodeIntegration: false }
});
win.loadURL('https://webrtc.github.io/samples/src/content/getusermedia/gum/');
win.on('close', () => {
app.quit();
});
});
問題点
先ほどの例では外部のコンテンツに対して何の確認もなくカメラへのアクセスを許可してしまいました。よって、ElectronのBrowserWindow
やwebview
で外部のコンテンツを表示したとき、XSSによって悪意あるコードが埋め込まれていてもカメラへのアクセスを許可してしまいます。
WebRTCを使ってカメラの映像やマイクの音声を垂れ流しにしたり、Geolocation APIで位置情報を盗んだりできるのではないでしょうか。(この辺りは詳しくないので、できないのかもしれませんが、攻撃者にデバイスへのアクセスを許してしまう時点であまり気持ちのいいものではないです)
対策
Session
オブジェクト(大抵はsession.defaultSession
)のses.setPermissionRequestHandler()
を使います。
ユーザーへの確認が必要なAPIを呼び出したときにコールバックが呼ばれるようになるので、判定結果をさらにコールバック関数へ渡します。確認方法自体は用意されていないので、dialog.showMessageBox()
をコールバック付きで使うのがお手軽です。