コース目次 / 第2章
CORS の基本 — サーバが開ける窓口
APIがAccess-Control-Allow-Originで正規のフロントを名指しで許可し、fetchが通る様子を見ます。単純リクエストとプリフライト(OPTIONS)の違いを押さえます。
前章で、正規のフロント(:4001)ですらブロックされました。読ませたいなら、API が明示的に許可を出す必要があります。その許可が CORS(Cross-Origin Resource Sharing) です。
法と倫理ゲート
手を動かす前に
このコースは攻撃の技術に触れます。実習してよい相手は、次の3つだけです。
- (a) 自分で作った練習用のやられ環境(このサイトが配る自作ターゲット)
- (b) あなた自身の許可された環境(自分の Thousand SKY・secret-notes-ctf など)
- (c) CTF 競技の中(規約の範囲で)
実在する第三者のシステムを許可なく触ることは、不正アクセス禁止法に触れます。 このゲートは、その線引きを毎回の入口で確かめるためのものです。詳しくは「セキュリティの法と倫理」へ。
窓口を、開ける
API(api.js)に、1行足します。「http://127.0.0.1:4001 には読ませてよい」と名指しで許可するヘッダです。
const server = http.createServer((req, res) => {
res.setHeader('Content-Type', 'application/json; charset=utf-8');
// CORS: このオリジンには、レスポンスを読ませてよい、と明示的に許可する。
res.setHeader('Access-Control-Allow-Origin', 'http://127.0.0.1:4001');
res.end(JSON.stringify({ secret: '架空太郎の口座残高: 1,234,567 円' }));
});
API を再起動して(Ctrl+C → node api.js)、ブラウザで http://127.0.0.1:4001 を再読み込みします。
今度は 「読めた: {“secret”:“架空太郎の口座残高: 1,234,567 円”}」と表示されます。Access-Control-Allow-Origin(ACAO)で名指しされた :4001 は、ブラウザに「このオリジンには読ませてよい」と伝わり、JS が中身を読めるようになりました。
確かめ方も押さえておきます——curl -i -H “Origin: http://127.0.0.1:4001” http://127.0.0.1:4000 とすると、レスポンスヘッダに Access-Control-Allow-Origin: http://127.0.0.1:4001 が乗っているのが見えます。判断材料はサーバが出し、実際に読ませるか止めるかはブラウザが決める——この分担が CORS の核です。
単純リクエストと、プリフライト
CORS には2つのモードがあります。診断でよく効くので、違いを押さえます。
単純リクエスト(simple request) — GET や、素朴な POST のように「昔からフォームでも送れた」種類のリクエスト。ブラウザはいきなり本番のリクエストを送り、返ってきた ACAO を見て「読ませてよいか」を事後に判断します。
プリフライト(preflight) — PUT/DELETE や、独自ヘッダ・JSON の Content-Type を伴うリクエストなど、「副作用がありそう」な種類。ブラウザは本番の前に、OPTIONS という下見のリクエストを自動で送り、「このメソッド・このヘッダで、そちらへ送ってよいか?」をサーバに問い合わせます。サーバが Access-Control-Allow-Methods などで許可を返して初めて、本番を送ります。
プリフライトに答えるには、API が OPTIONS を処理する必要があります。
// プリフライト(OPTIONS)への応答。許可するメソッド・ヘッダを返す。
if (req.method === 'OPTIONS') {
res.setHeader('Access-Control-Allow-Origin', 'http://127.0.0.1:4001');
res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS');
res.setHeader('Access-Control-Allow-Headers', 'Content-Type');
res.writeHead(204);
res.end();
return;
}
診断では、この OPTIONS のやり取りが宝の山です。プリフライトの応答を見れば、その API が「どのオリジン・どのメソッド・どのヘッダ・資格情報を伴うか」を、どう許可しているかが分かる。次章で突く誤設定も、多くはこの応答ヘッダに現れます。
CORS は「緩める」だけ
大事な位置づけを、もう一度。
CORS は、SOP を破る攻撃手段ではありません。SOP という既定の壁に、サーバが意図的に窓口を開ける仕組みです。正しく使えば、正規のフロントにだけ窓を開け、それ以外は壁のまま。
問題は——窓を、開けすぎたときに起きます。「誰にでも読ませる」「資格情報付きで誰にでも」といった緩めすぎが、壁を無意味にする。それが次章です。
持ち帰る一言
CORS は、サーバが名指しで開ける窓口。 Access-Control-Allow-Origin で許可したオリジンだけが、別オリジンのレスポンスを読める。判断材料はサーバが出し、ブラウザが強制する。プリフライト(OPTIONS)は副作用のあるリクエストの下見。では、この窓口を「開けすぎる」と何が起きるか。次章で穴を見ます。
こうなっていればOK
卒業まであと2章です。
この章はまだ完了していません。
保存できませんでした(プライベートブラウズ中かもしれません)。この端末に進捗は残りませんが、先へは進めます。