玄関の鍵はかけても「窓」が開いていませんか? JSONハイジャックの正体と防ぎ方
こんにちは!セキュリティの現場で日々、システムの脆弱性を探しているエンジニアです。
今日は、Web開発の現場でつい見落とされがちな「JSONハイジャック」という攻撃についてお話しします。難しそうな名前ですが、身近な「防犯」に例えると、その仕組みはとてもシンプルです。
1. JSONハイジャックって何?:泥棒の侵入経路
まず、Webサービスでのやり取りを想像してみてください。あなたがログインして、自分の個人情報をサーバーに問い合わせると、サーバーは「[{"name": "田中", "age": 25}]」のような配列形式のJSONデータを返してくれます。
通常、このデータはブラウザのプログラム(JavaScript)がこっそり受け取って表示するものです。しかし、ここで「泥棒(攻撃者)」の登場です。
泥棒は、あなたが別の悪意あるサイトを開いている隙に、あなたのブラウザを操って、その個人情報が載っているページを<script>タグとして読み込ませようとします。
- 正常な場合: 玄関(API)から正当な鍵(認証トークン)を使ってデータを受け取る。
- JSONハイジャック: 窓(
<script>タグ)から無理やりデータを取り込み、中身を別のプログラムで横取りしてしまう。
かつてのブラウザは、この「配列形式のJSON」をJavaScriptのプログラムの一部として実行できてしまうという性質がありました。これにより、攻撃者はあなたの個人情報をこっそり盗み出すことができたのです。
2. なぜ <script> タグで盗まれるの?
<script>タグは、本来「プログラムを読み込むためのもの」です。しかし、古いブラウザでは「JSONの配列([...])」も、「JavaScriptのコード」として解釈して実行しようとする癖がありました。
攻撃者は、あなたのブラウザに以下のような罠を仕掛けます。
<!-- 攻撃者のサイトがあなたのブラウザに読み込ませるコード -->
<script src="https://bank.example.com/api/user-info"></script>
本来、bank.example.com はあなたしか見られないはずのデータを返しますが、ブラウザはこのタグを見ると「お、スクリプトがあるな。実行しなきゃ!」と、そのJSONデータをプログラムとして処理してしまいます。攻撃者はあらかじめブラウザの機能を上書き(オーバーライド)しておき、そのデータが実行された瞬間に自分のサーバーへデータを送信するように仕組んでおくのです。
3. 今日からできる最強の防御:X-Content-Type-Options: nosniff
「じゃあ、どうやって窓を閉めればいいの?」という疑問が湧きますよね。ここで登場するのが、魔法の合言葉のようなヘッダー、X-Content-Type-Options: nosniff です。
このヘッダーは、ブラウザに対して「サーバーが言った中身のタイプ(Content-Type)を勝手に推測して解釈するな!」という強い命令です。
これをつけておくと、ブラウザは「これはJSON(データ)です」とサーバーが宣言したものを、無理やりJavaScriptのプログラムとして実行するのを止めてくれます。
実務での設定例
Webサーバー(ApacheやNginxなど)の設定ファイルに、以下のように記述するだけです。
Nginxの場合の例:
# 全てのレスポンスにヘッダーを追加する設定
add_header X-Content-Type-Options "nosniff" always;
Apacheの場合の例:
# .htaccess などに記述
Header set X-Content-Type-Options "nosniff"
これだけで、ブラウザは「JSONをスクリプトとして実行する」という危険な推測を止めてくれます。まさに、窓に頑丈な格子を取り付けるようなものです。
4. さらに一歩進んだ対策:JSONの先頭に細工を
もう一つの対策として、APIが返すJSONをあえて「配列([...])」ではなく、「オブジェクト({...})」にすることも有効です。
// 悪い例(配列:ハイジャックされやすい)
[{"name": "田中", "age": 25}]
// 良い例(オブジェクト:スクリプトとして実行してもエラーになる)
{"user": {"name": "田中", "age": 25}}
配列はJavaScriptではプログラムの一部に見えてしまいますが、オブジェクトの先頭に現れる{は、スクリプトとしては構文エラーになることが多いため、攻撃が成立しにくくなります。
まとめ:セキュリティは「推測させない」ことが肝心
JSONハイジャックは古い手法に見えますが、設定一つで確実に防げる「基本のキ」です。
1. X-Content-Type-Options: nosniff を必ず設定する。
2. APIのレスポンス形式を意識する(配列をそのまま返さない)。
「自分は大丈夫」と思わず、こうした設定を一つずつ積み重ねることが、あなたのサービスとユーザーを守る一番の近道です。今日から、サーバーのレスポンスヘッダーを一度確認してみてくださいね。
一歩ずつ、安全な開発を一緒に続けていきましょう!
コメント