なぜ「Permissions-Policy」を無視するのか?:ブラウザの蛇口を締め上げる防衛術
やあ。現場で泥をすすりながらインシデント対応をしているエンジニア諸君、今日も「動けば正義」のコードを書いていないだろうか?
今日は、多くの開発者が「なんとなく警告が出ないから」と放置しているPermissions-Policy(旧Feature-Policy)について話そう。これは単なるヘッダー設定じゃない。「ブラウザという名の強力なOS」の権限を、攻撃者の手から引き剥がすための最後の砦だ。
1. なぜこれが「攻撃の盲点」になるのか
Webアプリケーションの脆弱性として、XSS(クロスサイトスクリプティング)は今なお王様だ。仮に君のアプリにXSSの穴があったとしよう。攻撃者はどう動くと思う?
ただアラートを出すだけじゃない。ユーザーのブラウザを「盗聴器」や「GPSトラッカー」に変えるんだ。
- カメラ・マイクの悪用: `navigator.mediaDevices.getUserMedia()` を叩き、ユーザーの許可をすり抜けて(または既に許可済みの状態で)密かに映像や音声を録画・送信する。
- 位置情報の特定: `navigator.geolocation.getCurrentPosition()` で、ユーザーの正確な現在地を抜き出す。
これらはブラウザの「標準機能」だ。だから、WAFで不正な文字列を弾いていても、正規のAPIコールを止めることはできない。だが、Permissions-Policyを設定していれば話は別だ。「このブラウザ機能は、そもそもこのページでは動作させない」という制約を、ブラウザ自体に強制できるからだ。
2. PoC:もし制限がなかったら?
想像してほしい。攻撃者が埋め込んだ悪意あるスクリプトが、コンソールでこう叫ぶだけで、ユーザーのプライバシーが崩壊する現実を。
// 攻撃スクリプトのイメージ
navigator.mediaDevices.getUserMedia({ video: true, audio: true })
.then(stream => {
// 取得したストリームを外部サーバーへストリーミングする処理…
})
.catch(err => console.error(“残念、カメラにアクセスできませんでした”));
もし、君のアプリが「カメラ機能を使わない」設計なら、こんなコードが実行されること自体が異常だ。Permissions-Policyを設定していれば、ブラウザは即座にこのリクエストをブロックする。攻撃者は、たとえXSSに成功しても「カメラという凶器」には手が届かない。
3. 実践:Nginx/Apacheでの鉄壁の防御設定
Permissions-Policyは、HTTPレスポンスヘッダーで制御する。難しく考える必要はない。「自分たちのアプリで絶対に使う機能」以外をすべてオフにする、ホワイトリスト方式で設定すればいい。
Nginxの設定例
`nginx.conf` またはバーチャルホストの設定ファイルに以下を追記する。
カメラ、マイク、位置情報、決済機能などを無効化する例
add_header Permissions-Policy “camera=(), microphone=(), geolocation=(), payment=(), usb=()”;
Apacheの設定例
`.htaccess` または設定ファイルに以下を追記する。
# ブラウザの機能を徹底的に制限する
Header always set Permissions-Policy “camera=(), microphone=(), geolocation=(), payment=(), usb=(), interest-cohort=()”
ポイント: `()` は「どのオリジンにも許可しない(無効)」を意味する。もし特定のドメインでカメラを使いたいなら、`camera=(self “https://trusted-domain.com”)` のように記述すればいい。
4. アプリケーションコード(PHP/Python)での実装
サーバーサイドで動的に制御したい場合、あるいはフレームワークのミドルウェアとして実装したい場合はこうなる。
PHPでの実装例
Python (Flask) での実装例
@app.after_request
def add_security_headers(response):
# セキュアなヘッダーを付与
response.headers[‘Permissions-Policy’] = ‘camera=(), microphone=(), geolocation=(), payment=()’
return response
5. エンジニアへのアドバイス:運用でハマらないために
最後に、現場でよくある失敗を一つ。「とりあえず全部拒否したら、サイトの地図表示(Google Maps等)が消えた」というケースだ。
`geolocation` を `()` にすると、位置情報APIを使うライブラリはすべて動かなくなる。自分が使っている外部ライブラリがどのAPIを呼び出しているのか、Chromeの「デベロッパーツールのConsoleタブ」を見て確認してほしい。ブロックされた機能は、ブラウザが親切にエラーログを出してくれるはずだ。
結び:セキュリティは「足し算」ではなく「引き算」
強固なシステムとは、「不要なものを極限まで削ぎ落としたシステム」のことだ。Permissions-Policyは、君のWebアプリの攻撃対象領域(Attack Surface)を物理的に削る強力なツールになる。
今日、デプロイする前にヘッダーを確認してくれ。もし設定されていなければ、それは「鍵の開いた玄関」と同じだ。さあ、今すぐ設定して、君のアプリケーションを鉄壁にしよう。
何かあれば、またいつでも聞いてくれ。現場からは以上だ。

コメント