わかったフリはやめよう!セキュリティ基礎
はじめに
アサヒに、アスクル・・・大手企業へのサイバー攻撃が相次いで報じられています。開発者としてこのようなニュースに触れると、緊張感が走ります。。
さらに、近年はバイブコーディングが広がりつつありますが、具体的なセキュリティ要件を明示しなければ、AIが脆弱性を含むコードを生成してしまうケースも少なくありません。
だからこそ、開発者自身が正確なセキュリティの知識を身につけ、「どんな脆弱性があるのか」「どうしたら対策できるのか」を理解し、AIに的確な指示を出せることが重要です。
本記事では、アプリケーション開発における基礎的なセキュリティ課題を、ハッカーの視点から整理し、どのように防げるのかを見ていきます!
ハッカーのアプローチ
私たち開発者は通常、以下のようなアプローチで開発しています。
- 何が問題なのか
- 問題を解決する最も単純な方法は何か
- テスト:問題は解決されたか
- 解決方法を改善することはできるか
しかし、ハッカーのアプローチは異なり、下記のアプローチによって攻撃するとこちらの書籍では説明しています。
- どのように動作するのか
- どうすれば突破できるか
- 他にどんな動作をさせられるか
- それによって何ができるか
両者のアプローチは正反対であるため、対策を行うには ハッカーがどのように考え、活動するのかを理解することが必要 です。
したがって、本記事ではハッカーのアプローチに沿ってシナリオ例を挙げ、その上で対策方法をご紹介します!
シナリオ例
今回は、ログインしてパスワードを変更する単純な操作を例として挙げます。
今回記事にするにあたり徳丸さんのこちらのYouTubeチャンネルが大変わかりやすかったので参考にしています!
どのように動作するのか
以下は、脆弱性を含む認証ページの例です。
- ユーザーがログインページにアクセスする
-
ログインページからログインする
- このときサーバーから セッションID が発行され、Cookie とサーバー上の セッション変数 に保存される。
- ログインしているサイトから、パスワードを変更するためにユーザー詳細画面にアクセスする
-
新しいパスワード(例:
newpass)をリクエストボディに含めてサーバーへ送信する- このときブラウザの仕様により、Cookie 内のセッションID も自動的にサーバーへ送られる。
- サーバー側では、送信された Cookie の セッションID とサーバー上の セッション変数に保存されているセッションID が一致しているか確認する。
- 一致していれば、パスワードを正常に更新する。

どうすれば突破できるか
※ 攻撃手法の詳細は後述します。
他にどんな動作をさせられるか
- 入手した認証データを用いて、対象アカウントのパスワードを強制的にリセットする
-
攻撃で想定される不正操作
- 他ユーザーとしてのログイン(なりすまし)
- アカウント設定の変更(メールアドレス、2FA設定、プロフィール等)
- 支払い操作やトランザクションの不正実行(取引の承認や送金など)
- アクセス権限の横展開(権限昇格、データ漏洩)
それによって何ができるか
- 個人情報や機密情報へのアクセス/漏洩
- 金銭的被害(不正支払い、チャージ等)
- サービスの信頼性低下、顧客離脱、法的・規制上の問題
などなど
攻撃手法 ①
上記「どのように動作するのか」の 1〜2 を実施したのち、
-
ログインした状態で、罠サイトにアクセスする
- 罠サイトに仕掛けられたフォームの自動送信処理が実行される。
- Cookie は自動送信されるため、認証が成功し、正常に新しいパスワード(例:
evil)にパスワードが更新される

これがいわゆる CSRF攻撃 です。
対策として下記4つをご紹介します。
対策:CSRFトークン
まず代表的な対策として、 CSRFトークン というものがあります。
上記「どのように動作するのか」の 1〜2 を実施したのち、
-
ユーザー詳細画面にアクセスする
- このとき CSRFトークン をサーバーで生成し、hidden パラメーター と サーバー上の セッション変数 に保存する。
-
新しいパスワード(例:
newpass)をリクエストボディに含めてサーバーへ送信する- サーバー側では、送信された hidden パラメーターの CSRFトークン とサーバー上の セッション変数に保存されているCSRFトークン が一致しているか確認する。
- 一致していれば、パスワードを正常に更新する。
※ ログイン部分のシーケンス図は割愛してます

罠サイトの場合、hidden パラメーターの CSRFトークンの値が不明 であるため、攻撃は失敗します。
※ ログイン部分のシーケンス図は割愛してます

対策:Double Submit Cookie
上記の CSRFトークン の方法はステートフルな実装です。
ステートレスに実装したい場合は Double Submit Cookie が緩和策として挙げられます。
上記「どのように動作するのか」の 1〜2 を実施したのち、
-
ユーザー詳細画面にアクセスする
- このとき CSRFトークン をサーバーで生成し、Cookie と hidden パラメーター に保存する。
-
新しいパスワード(例:
newpass)をリクエストボディに含めてサーバーへ送信する- 送信された Cookie と hidden パラメーター の値が一致するか確認する。
- 一致していれば、パスワードを正常に更新する。
※ ログイン部分のシーケンス図は割愛してます

罠サイトの場合、Cookie は送信されますが、同一オリジンポリシーにより罠サイトからは Cookie の値を読み取れません。
したがって、hidden パラメーターの CSRFトークンの値が不明 であり、攻撃は失敗します。
※ ログイン部分のシーケンス図は割愛してます

対策:Bearer Token
ステートレスな方法としてもう一つあります。それが Bearer Token です。
- ユーザーがログインページにアクセスする
-
ログインページからログインする
- このときサーバー側は署名付きのアクセストークンを発行し、レスポンスボディ に含めてクライアントへ返す。
- クライアントは受け取ったアクセストークンを localStorage に保持する。
- ログインしているサイトから、パスワードを変更するためにユーザー詳細画面にアクセスする
-
新しいパスワード(例:
newpass)をリクエストボディに含めてサーバーへ送信する- このときリクエストヘッダーにトークンを付与して送信する。
※ localStorage は Cookie と異なり、ブラウザによって自動的にサーバーへ送られることはない。 - サーバーは受け取ったトークンを検証する。
- トークンの署名が正しいか(改ざんされていないか)
- トークンの有効期限が切れていないか
- トークンに含まれる発行者や対象が正しいか
- 検証が成功すれば、パスワードを正常に更新する。
- このときリクエストヘッダーにトークンを付与して送信する。

罠サイトの場合、localStorage に保存されたアクセストークンは自動的に送信されません。
そのため、罠サイトからのリクエストではトークンが付与されず、攻撃は失敗します。

対策:SameSite=Lax
上記対策では、異なるオリジンから Cookie を送信できる前提で説明していましたが、
これをブラウザレベルで制御する方法があります。
それが SameSite=Lax です。
SameSite=Lax を設定すると、ブラウザは以下のように動作します。
-
GET の場合:
異なるオリジンからでも Cookie を送信可能 -
GET 以外の場合(例:POST, PUT, DELETE など):
異なるオリジンからの Cookie 送信は不可
したがって、罠サイトからのリクエストでは Cookie に保存されたセッションIDが送信されず、攻撃は失敗します。

ちなみにSameSite=LaxはChromeの現在のデフォルト設定です。
攻撃手法 ②
攻撃手法 ① に対して対策をいくつか挙げましたが、まだ脆弱性があります。
上記「どのように動作するのか」の 1〜2 を実施したのち、
- ログインした状態で、罠サイトにアクセスし、罠サイトに仕掛けられたリンクをユーザーがクリックする
-
リンクに仕掛けられたスクリプトが発火する
- スクリプトによりフォームの自動送信処理が実行される。
- Cookie は自動送信されるため、正常に新しいパスワード(例:
evil)にパスワードが更新される
※ ログイン部分のシーケンス図は割愛してます

これがいわゆる反射型XSSです。
CSRFとXSSには下記のような違いがあります。
| CSRF | XSS | |
|---|---|---|
| 攻撃元 | 異なるオリジン からの攻撃 | 同一オリジン からの攻撃 |
| 対象となるリクエスト | 更新系の処理のみ | 更新系だけでなく画面表示なども含めたあらゆる処理 |
| 影響を受けるサイト | Cookie でセッション管理しているサイト のみ | 動的にデータを表示しているサイト(ほぼ全て) |
上記の通り、XSSの方が影響範囲は大きい です。
CSRFとは異なり、XSSは同一オリジン内で発生する攻撃 のため、SameSite=Lax や CORS は対策になりません。
では対策としてどのようなものがあるか下記に挙げます。
対策:エスケープ処理
出力時に HTML 表示に影響する特殊文字を HTML エンティティ に置換します。
主な置換例:
-
<→< -
>→> -
&→& -
"→" -
'→'
するとブラウザがこれらを文字列として扱うようになるため、埋め込まれた <script> 等が実行されず、攻撃は失敗します。

まとめ
今回は ハッカーのアプローチ をもとに、セキュリティリスクについてご紹介しました。
とても基礎的な内容ではありましたが、ただ対策を知るだけでなく、ハッカーがどのようなアプローチを取るのかを理解することによって、「どのようにすれば根本から対策できるか」「なぜその対策が有効なのか」を考えることができます。
このような思考力こそが、バイブコーディング が進んでいる現在において、開発者に求められる重要なスキルだと考えます。
今回は基礎的な内容を取り上げましたが、
今後はWeb3を扱う会社らしくWeb3についてのセキュリティについても記事にしていきたいと思います!
Discussion