
Webサイトで起こる3つの代表的な攻撃を学ぶ
Webサイトで起こる3つの代表的な攻撃
入力値・表示・ログイン中の操作を狙う3つの攻撃
Webサイトは、ブラウザ(ChromeやSafariなどの閲覧アプリ)からWebサーバーへ、リクエスト(処理の依頼)を送って動きます。Webサーバーは必要に応じて、データベース(情報を保存・検索する仕組み)を使って結果を返します。
セキュリティ上の問題は、外部から受け取った値を、本来のデータではなく命令として扱ってしまうことで起こります。また、ログイン中の利用者の状態だけを見て、本人が意図した操作だと誤って判断することでも起こります。
この記事では、SQLインジェクション、XSS、CSRFの3つを取り上げます。攻撃用の具体的な文字列は扱いません。どこから情報が入り、どこで問題が起き、何を確認すればよいのかを順番に見ていきます。

3つの攻撃は、狙われる場所が違う
Webサイトでは、ブラウザからWebサーバーへリクエストが送られます。サーバーは必要に応じてデータベースを読み書きし、その結果をブラウザへ返します。

3つの攻撃は名前も仕組みも異なりますが、データの流れに沿って見ると整理しやすくなります。
- SQLインジェクションは、入力値がデータベースへの命令に混ざる問題
- XSSは、表示した内容が利用者のブラウザで命令として動く問題
- CSRFは、ログイン中の利用者に意図しない操作をさせる問題
共通しているのは、外部から来たものを、使う場所に合った方法で扱う必要があることです。
1. SQLインジェクション:入力値がデータベースへの命令になる
SQLは、データベースに検索や更新を指示するための言語です。検索画面やログイン画面では、利用者が入力した文字を使ってデータベースを検索します。このとき、SQL文と入力値を文字列として直接つないでしまうと、入力値の一部がSQLの命令として解釈される場合があります。これがSQLインジェクションです。

危険なのは「文字列を受け取ること」ではなく「SQLへ混ぜること」
以下は、仕組みを説明するための概念例です。実際の書き方は、使用するプログラミング言語やデータベースライブラリによって異なります。
次のように入力値をSQL文へ直接つなぐ作り方は危険です。
sql = "SELECT ... WHERE email = '" + 入力値 + "'"
この形では、プログラムが用意したSQLと、利用者が送った値の境界が曖昧です。入力内容によっては、データベースが全体を1つの命令として解釈してしまいます。
一方、パラメータ付きクエリでは、SQLの構造と値を分けて渡します。
sql = "SELECT ... WHERE email = ?" db.query(sql, 入力値)
データベースは「?」に渡された内容を検索値として扱います。入力にSQLのような文字が含まれていても、命令の構造を変えにくくなります。
成立すると何が起きるのか
SQLインジェクションが成立した場合、影響は検索結果の変化だけにとどまりません。アプリケーションに与えられたデータベース権限によっては、次のような被害へ広がります。
- 本来は見られない情報を取得される
- 利用者情報や設定を書き換えられる
- データを削除される
- 認証処理を回避される
アプリケーションの接続アカウントに強すぎる権限があると、被害も大きくなります。
基本対策と補助対策を分けて考える
中心となる対策は、 プリペアドステートメントやパラメータ付きクエリを使い、SQLと値を分離すること です。SQL用のエスケープ処理だけに頼ると、データベースや文字コードの違い、実装漏れなどで破られるおそれがあります。
入力値の形式チェックも必要です。年齢なら数値、識別子なら決められた形式というように、仕様に合わない値を早い段階で拒否します。ただし、形式チェックはパラメータ付きクエリの代わりにはなりません。
テーブル名や並び順など、パラメータとして渡せない部分を動的に切り替える場合は、プログラム側で許可した候補から選びます。さらに、アプリケーションがデータベースへ接続するアカウントの権限を必要最小限にし、万一のときに被害が広がりにくい構成にします。
2. XSS:表示した内容がブラウザで実行される
掲示板、プロフィール、検索結果などでは、利用者が入力した内容を画面に表示します。このとき、文字として表示するはずの内容がHTML(画面の構造)やJavaScript(画面で動くプログラム)として解釈されると、別の利用者のブラウザで悪意のある処理が動く可能性があります。これがXSS(クロスサイト・スクリプティング)です。

XSSには複数の入り方がある
XSSは、悪意のある内容がどこを通るかによって整理できます。
- 保存型XSS :投稿内容やプロフィールなどに悪意のある文字列が保存され、別の利用者がその画面を開いたときに影響します。
- 反射型XSS :URLの検索条件やエラー内容など、リクエストに含まれた値がすぐ画面へ返されます。
- DOMベースXSS :ブラウザ上のJavaScriptがURLや入力値を読み取り、危険な方法で画面を書き換えます。サーバー側のHTMLに問題が見当たらなくても、ブラウザ内の処理だけで成立する場合があります。
3つを暗記するより、「外部から来た値が、ブラウザでコードとして解釈される場所へ入っていないか」と考える方が実装時には役立ちます。
成立すると何が起きるのか
XSSが成立すると、攻撃者の処理が正規サイトの画面内で動きます。そのため、利用者からは本物の画面との区別がつきにくくなります。
- 偽のログイン画面や入力欄を表示させられる
- 画面上の情報や利用者の操作を読み取られる
- 利用者の権限でWebサイトの機能を操作される
- 不正なページへ誘導される
Cookieに「HttpOnly」(JavaScriptからCookieを読み取れないようにする属性)を設定すると、Cookieの盗難を防ぐ助けになります。ただし、XSSそのものを防ぐ設定ではありません。悪意のある処理が正規画面上で動けば、Cookieを盗めなくても利用者の権限で操作できる場合があります。
表示する場所に合った処理が必要
基本は、値を画面に出す直前に、 表示先に合った方法で処理すること です。HTML本文、HTML属性、URLなど、表示する場所によってルールが異なります。
多くのフレームワークには自動エスケープの機能があります。まずは既定の安全な表示方法を使い、外部から受け取った値をinnerHTMLへ直接渡さないようにします。innerHTMLは、文字列をHTMLとして解釈する仕組みです。一方、単なる文字列を表示する場合は、textContentのように文字列として扱う方法を使います。
記事投稿などで一部のHTMLを許可する場合は、危険な要素や属性を取り除くHTMLサニタイズを行います。
XSS対策では、出力先に合った処理を使い、未検証の値をHTMLとして解釈する処理へ直接渡さないことが重要です。
3. CSRF:ログイン中の利用者に意図しない操作をさせる
CSRF(クロスサイト・リクエスト・フォージェリ)は、攻撃者が利用者のパスワードを盗んでログインする攻撃とは異なります。すでにログインしている利用者のブラウザを踏み台にして、本人が意図していないリクエストを正規サイトへ送らせる攻撃です。

ブラウザがCookieを自動送信する性質を利用する
利用者がWebサイトへログインすると、ブラウザにはセッションを識別するCookieが保存されます。対象サイトへのリクエストでは、ブラウザがCookieを自動的に付ける場合があります。
この状態で利用者が攻撃者の用意した別サイトを開くと、そのページから正規サイトへリクエストを送らされることがあります。正規サイトがCookieだけを見て本人の操作だと判断すると、利用者が意図していない処理まで実行されます。
CSRFが成立するには、主に次の条件が重なります。
- 利用者が対象サイトへログインしている
- ブラウザが認証用Cookieを自動的に付ける
- データを変更する処理が外部サイトから送信できる
- サーバーが操作の出所やトークンを確認していない
成立すると何が起きるのか
被害は、ログイン中の利用者に許可されている操作の範囲で起こります。
- メールアドレスや通知設定を変更される
- データを登録・更新・削除される
- 意図しない申込みや送信処理を実行される
- 管理者が狙われた場合、管理機能を操作される
複数の確認を組み合わせる
代表的な対策は、サーバーが発行した CSRFトークン をフォームやリクエストに含め、更新処理の前に一致を確認することです。通常、攻撃者が用意した別サイトからは正しいトークンを取得できないようにすることで、不正なリクエストを拒否します。
Cookieの「SameSite」属性は、別サイトからのリクエストにCookieを付ける条件を制限します。ただし、SameSiteだけに頼らず、CSRFトークンや送信元の確認も組み合わせます。
サーバー側で「Origin」(送信元を示す情報)や「Referer」(直前のページを示す情報)を確認し、想定した送信元から来たリクエストか検証する方法もあります。
データを変更する処理には、GET(ページ表示や検索など、状態を変えない用途)を使いません。POSTへ変えるだけでCSRF対策が完了するわけではありませんが、リンクを開いただけで状態が変わる設計は避ける必要があります。
CSRF対策では、更新・削除処理にトークンや送信元の確認を適用し、GETでデータを変更しないことが重要です。
3つの違いは「どこで意味が変わるか」で見分ける

| 攻撃 | 起きる場所 | 起きること | 主な対策 |
|---|---|---|---|
| SQLインジェクション | データベース | 値がSQLの命令になる | パラメータ付きクエリ |
| XSS | 利用者のブラウザ | 値が画面上のコードになる | 文脈に合ったエスケープ |
| CSRF | Webサイトの更新処理 | 外部からの送信が本人の操作になる | CSRFトークンと送信元確認 |
SQLインジェクションとXSSは、データが命令として解釈される点が似ています。ただし、命令を実行するのは前者がデータベース、後者がブラウザです。CSRFは入力値の解釈よりも、リクエストを送ったのが誰の意図なのかが問題になります。
セキュリティ対策は境界ごとに重ねる
単独の対策ですべてを防ぐことはできません。入力値を確認し、SQLと値を分け、画面に表示するときは文字として扱い、データを更新するときは操作の出所を確認します。

このように複数の対策を重ねる考え方を「多層防御」と呼びます。1つの対策に頼らず、別の対策でも被害を防いだり小さくしたりします。
よくある誤解

「入力チェックをすれば、すべて防げる」
入力チェックは、仕様外の値を早く拒否するために有効です。しかし、自由入力には記号や改行が正当なデータとして含まれることもあります。入力時に危険そうな文字をすべて削除すると、機能を壊したり、別の経路から来たデータを見落としたりします。
入力チェックに加えて、データがSQLになる場所、HTMLになる場所、更新リクエストとして処理される場所で、それぞれに合った対策を行います。
「POSTならCSRFは起きない」
別サイトからPOSTリクエストを送信させる方法はあります。POSTは「データを変更する処理で使うHTTPメソッド」であり、それだけで送信者の正当性を証明するものではありません。
「WAFやCSPがあれば実装側は直さなくてよい」
WAFやCSPは補助的な防御層です。値と命令を混ぜている実装は、アプリケーション側で修正する必要があります。
実装とレビューで使えるチェックリスト
設計時
- どの画面やAPIで外部から値を受け取るか
- 受け取った値が、データベース・HTML・URL・JavaScriptのどこへ渡るか
- データを変更する処理はどれか
- 利用者、一般管理者、システム管理者で権限が分かれているか
実装時
- SQLはパラメータ付きクエリで実行する
- 出力時はフレームワークの安全なAPIを優先する
- HTMLを許可するときはサニタイズする
- 更新処理ではCSRFトークンや送信元を検証する
- Cookieに用途に合った属性を設定する
- エラーへ内部情報や入力内容を出しすぎない
テスト時
- 通常の値だけでなく、空文字、長い文字列、記号を含む値も確認する
- 権限のない利用者がデータを更新する機能を実行できないことを確認する
- CSRFトークンがない、または一致しないリクエストが拒否されることを確認する
- 投稿内容がHTMLとして解釈されず、文字として表示されることを確認する
- 静的解析や依存ライブラリの脆弱性検査も併用する
最後に、次の3点を確認します。
- 入力値を命令と分けて扱っているか
- 表示内容を、画面上のコードとして実行させていないか
- リクエストが、本当に利用者の意図した操作か確認しているか
入力値・表示内容・リクエストを、そのまま信用しない。
確認する場所は3つです。SQLを組み立てるとき、画面に表示するとき、データを更新するとき。それぞれの場所で、値やリクエストを正しく扱えているかを確認します。
用語
- ブラウザ :Webサイトを表示し、サーバーと通信するアプリケーション
- SQL :データベースに検索や更新を指示するための言語
- API :別のソフトウェアから機能を呼び出すための窓口
- Webサーバー :ブラウザからリクエストを受け取り、処理結果を返すサーバー
- データベース :利用者情報やサービスのデータを保存・検索する仕組み
- Cookie :ログイン状態などをブラウザ側で保持するための情報
- エスケープ :特別な意味を持つ文字を、単なる文字として扱える形へ変換する処理
- サニタイズ :HTMLなどから、危険な要素や属性を取り除く処理
- オリジン :通信先を「スキーム・ホスト・ポート」の組み合わせで区別する考え方
- 許可リスト :利用を認める値や形式をあらかじめ決め、それ以外を拒否する方式
- HttpOnly :JavaScriptからCookieを読み取れないようにする属性
- SameSite :別サイトからのリクエストにCookieを付ける条件を制限する属性
- WAF :Webへの通信を監視し、不審な通信を遮断する仕組み
- CSP :ブラウザが読み込めるスクリプトなどを制限する仕組み