「APIにCSRF対策は不要?」その理由を、泥棒と合鍵の例えで解き明かす
こんにちは!セキュリティの世界へようこそ。日々、脆弱性診断やインシデント対応の現場に立っていると、「教科書にはこう書いてあるけど、結局なぜそうなるの?」という疑問にぶつかることがよくありますよね。
今日は、開発現場で避けては通れない「API認証とCSRF(クロスサイトリクエストフォージェリ)」の関係についてお話しします。「Bearerトークンを使っていればCSRFは気にしなくていい」と聞いたことはありませんか? なぜそんな魔法のようなことが言えるのか、身近な例えを交えて紐解いていきましょう。
—
そもそも、CSRF(泥棒)は何を狙っているのか?
CSRFを一言で言うと、「あなたのブラウザを悪用して、勝手に命令を実行させる攻撃」です。
想像してみてください。あなたは今、銀行のWebサイトにログインしたまま、別のタブで「怪しい懸賞サイト」を開いてしまいました。この懸賞サイトが裏であなたの銀行サイトに対して「100万円送金しろ!」という命令を勝手に送ったらどうなるでしょう?
もし、その銀行サイトが「ブラウザが自動的に送るCookie(ログイン状態を証明する鍵)」だけで本人確認をしていたら、銀行側は「あ、ログイン中の本人だ!送金しなきゃ!」と勘違いして、大事な預金を盗まれてしまいます。これがCSRFの恐ろしいメカニズムです。
なぜ「Bearerトークン」だと攻撃が防げるのか?
では、なぜAPIで「Bearerトークン(Authorizationヘッダー)」を使うと、この泥棒が侵入できなくなるのでしょうか。
1. 「Cookie」は自動でついてくる、厄介な鍵
ブラウザのCookieは、特定のドメインに対して「勝手にブラウザがくっつけて送信する」という性質があります。これが泥棒の最大の武器です。泥棒はあなたのブラウザに「鍵を渡せ」と言うだけで、ブラウザが勝手に鍵を添えて銀行サイトへ突撃してくれるのです。
2. 「Authorizationヘッダー」は、自分から差し出す鍵
一方、Bearerトークンは「Authorization: Bearer <トークン文字列>」という形式で送ります。これはCookieとは異なり、ブラウザが勝手に付与することはありません。
開発者がプログラムコードの中で、「よし、このAPIを叩くときは、ちゃんとヘッダーにトークンをセットしよう」と明示的に書かない限り、鍵は送信されません。
ここが最大のポイントです。
悪意のあるWebサイト(泥棒)が、あなたのブラウザを使ってAPIを叩こうとしても、泥棒側はあなたのトークンを知りません。そして、ブラウザも気を利かせてトークンを勝手に付与してはくれません。結果として、API側には「鍵がありませんよ」と弾かれ、攻撃は失敗に終わるのです。
—
実装で気をつけるべき「たった一つのポイント」
「じゃあ、Bearerトークンさえ使っていれば、何もしなくていいんだね!」……と言いたいところですが、一つだけ注意が必要です。
もし、「Cookieでもトークンでも、どっちでも認証OKですよ」というAPIを作ってしまったらどうなるでしょう? そう、泥棒は「じゃあCookieで通してやる!」と、元の木阿弥になってしまいます。
実装の際のチェックリスト
- 認証は一本化する: APIにはBearerトークンのみを受け入れる設計にする。
- Cookie認証を併用しない: どうしてもCookieを使う必要がある場合、それはCSRF対策が必須の「Web画面用」として分離し、APIとは別のエンドポイントにする。
- CORSの設定: もしブラウザからAPIを叩かせるなら、CORS(Cross-Origin Resource Sharing)設定で「信頼できるドメイン以外からのアクセスは拒否する」という壁をしっかりと築いてください。
実装イメージ(Node.js / Expressの例)
// 良い例:Authorizationヘッダーからのみトークンを取得する
app.get(‘/api/user-info’, (req, res) => {
const authHeader = req.headers[‘authorization’];
// そもそもヘッダーがない、または形式が違うなら即座に拒否
if (!authHeader || !authHeader.startsWith(‘Bearer ‘)) {
return res.status(401).send(‘認証エラー:トークンが必要です’);
}
const token = authHeader.split(‘ ‘)[1];
// ここでトークンの検証を行う
// …
});
—
まとめ:セキュリティは「仕組み」で解決する
「BearerトークンならCSRF対策不要」というのは、サボっていいという意味ではなく、「認証の仕組み自体が、CSRFという攻撃手法を無効化している」という状態なのです。
セキュリティ対策は、ガチガチに防壁を固めるだけでなく、今回のように「そもそも攻撃が成立しないアーキテクチャを選ぶ」という考え方が非常に重要です。
これから開発を行う際は、ぜひ「この認証方式は、ブラウザが勝手に鍵を運んでしまわないか?」という視点を忘れないでくださいね。一歩ずつ、安全なアプリケーションを作っていきましょう!
もし、「ここがまだモヤモヤする」という点があれば、またいつでも聞いてください。現場の泥臭い知見を交えて、また一緒に考えましょう!
コメント