なぜ「JSONP」が狙われるのか?泥棒が合鍵を作るメカニズムを解き明かす
こんにちは。現場の最前線でセキュリティと向き合っていると、時折「昔ながらの技術」が思わぬ落とし穴になっている場面に出くわします。その代表格がJSONP(JSON with Padding)です。
一見便利な技術に見えますが、セキュリティの観点から見ると、これは「玄関の鍵を閉めずに、知らない誰かを家の中に招き入れる」ような危うさを持っています。今回は、なぜこれがXSS(クロスサイトスクリプティング)の温床になるのか、そして私たちがどうやってこの泥棒から身を守るべきかを、一緒に紐解いていきましょう。
—
1. JSONPってそもそも何?(家の例えで考えてみよう)
JSONPは、本来「別のドメインにあるデータをもらいたい」という願いを叶えるための古い技術です。
想像してみてください。あなたは自分の家(WebサイトA)にいて、隣の家(WebサイトB)にある「今日の天気」というメモを借りたいとします。
通常、ブラウザには「他の家のメモを勝手に覗いてはいけない(同一生成元ポリシー)」という厳しいルールがあります。でも、「隣の家の人が、自分の家の玄関先までメモを届けてくれる」なら話は別ですよね。
JSONPでは、こんなやり取りをします。
1. あなた:「『天気教えて』という手紙を渡すから、関数callbackを使って返してね!」
2. 隣の人:「分かった!callback({"weather": "sunny"})という形で投げるよ」
一見平和ですが、ここに「泥棒」が付け入る隙があります。
—
2. 攻撃者が狙う「コールバック関数の悪用」
泥棒(攻撃者)は、このcallbackという名前を勝手に書き換えてしまいます。
あなたが「callbackという関数で返して」と言っている隙に、泥棒がURLのパラメータを操作して、「alert('お前の個人情報は俺のものだ!')という関数で返してくれ」とすり替えるのです。
すると、WebサイトBは善良な心で、攻撃者が指定した「悪意あるコード」をあなたのブラウザに送り届けます。ブラウザは「隣の家が送ってきたものだから安全だよね!」と信じ込み、そのコードをそのまま実行してしまいます。これがJSONPによるXSS攻撃の正体です。
—
3. どうやって防げばいいの?「CORS」という新しい鍵
「じゃあ、どうすれば安全にデータをやり取りできるの?」という疑問が湧きますよね。その答えがCORS(Cross-Origin Resource Sharing:クロスオリジンリソース共有)です。
CORSは、JSONPのような「泥棒を招き入れる」方法とは異なり、「どの家の人なら入っていいか」を玄関の表札(レスポンスヘッダー)に明記する仕組みです。
サーバー側の設定(例:Node.js / Express)
サーバー側で以下のように設定することで、特定の信頼できるドメイン以外からのアクセスをピシャリと拒否できます。
// 信頼できるドメインのみを許可する設定
const cors = require(‘cors’);
const corsOptions = {
// 許可するドメインを明記する(「」と書くと誰でも入れてしまうので注意!)
origin: ‘https://your-trusted-site.com’,
optionsSuccessStatus: 200
};
app.use(cors(corsOptions));
なぜこれが安全なの?
CORSでは、ブラウザがサーバーに対して「このサイト、入ってもいい?」と事前に確認(プリフライトリクエスト)を行います。サーバー側で許可されたドメインでなければ、ブラウザはデータを読み込むことすらさせません。これは、門番がしっかり身分証を確認するのと同じです。
—
4. まだJSONPを使わなければならない場合…
古いシステムとの兼ね合いで、どうしてもJSONPを捨てられないという現場もあるでしょう。その場合は、最低限の「防犯対策」を施してください。
- コールバック関数の名を固定する: ユーザーからの入力を受け取らず、サーバー側で関数名を決め打ちにします。
- ホワイトリスト化: もし動的に変える必要があるなら、許可された関数名リスト(例:
['callback1', 'callback2'])以外は受け付けないように厳密にチェックします。 - Content-Typeを固定:
application/javascriptではなく、application/jsonを強制し、ブラウザがスクリプトとして解釈するのを防ぎます。
—
最後に:セキュリティは「疑うこと」から始まる
ITの世界も、現実の防犯と同じです。「便利な機能には、必ず影がある」と疑う姿勢こそが、最高峰のエンジニアへの第一歩です。
JSONPは、インターネットの歴史において多くの貢献をしましたが、現代においては「レガシー(遺物)」です。もし皆さんのコードの中にJSONPが残っていたら、それは「鍵の壊れた玄関」を放置しているのと同じこと。ぜひ、今日からCORSへの移行を検討してみてください。
一歩ずつ、着実に。皆さんの手で、より安全なWebの世界を作っていきましょう!
コメント