DVWA(Damn Vulnerable Web Application)は、わざと脆弱に作られたPHP/MariaDB製のWebアプリケーションです。SQLインジェクションやXSSといった代表的なWeb脆弱性を、自分の手で攻撃し、同じ機能の安全な実装と見比べながら学べます。本記事では公式GitHubリポジトリ(digininja/DVWA・GPL-3.0)の最新ソース(2026年10月17日時点のmasterブランチ・コミット068d974)を一次情報に、環境構築・ログイン・セキュリティレベル・学べる脆弱性を、実際のソースコードの差分まで踏み込んで整理します。さらに、安全な実装(impossibleレベル)が日本の代表的なガイドラインIPA「安全なウェブサイトの作り方」のどの根本的解決に対応するかも対応づけます。
まとめ:DVWAの要点
- 正体:Damn Vulnerable Web Applicationの略。PHP+MariaDBで動く「意図的に脆弱な」学習用Webアプリ。ライセンスはGPL-3.0。
- 構築:公式が唯一サポートするのはGitHubの最新ソース。最短は公式Dockerで、
docker compose up -d後にhttp://localhost:4280で開く。 - 初期ログイン:ユーザー名
admin/パスワードpassword。初回は「Setup DVWA」でデータベースを作成する。 - セキュリティレベル:low/medium/high/impossibleの4段階。設定ファイルの既定値はimpossible(安全側)で、演習時は自分でlowへ下げる。
- 鉄則:インターネットに公開しない。ローカル環境(VMやローカルループバック)だけで動かす。
DVWAの正式名称・目的・ライセンス
DVWAはDamn Vulnerable Web Applicationの頭字語で、日本語では「非常に脆弱なWebアプリケーション」と説明されます。開発目的はREADMEに明記されており、(1)セキュリティ担当者が自分のスキルとツールを合法的な環境で試すこと、(2)Web開発者が防御の仕組みを理解すること、(3)教室など管理された場でWebセキュリティを学ぶこと、の3点です。
実体はPHPで書かれたWebアプリで、データベースにMariaDB(またはMySQL)を使います。ライセンスはGPL-3.0で、ソースコードはGitHubの digininja/DVWA で公開されています。攻撃対象のコードを画面上でそのまま閲覧できる(各モジュールの「View Source」)ため、「なぜ攻撃が通るのか」をコード単位で確認できるのが、単なる練習用サイトとの違いです。
脆弱性を体系的に学ぶ土台として、まず脆弱性の種類とCVE/CVSSの基礎を押さえてからDVWAに触れると、各モジュールが何の脆弱性を再現しているのかが掴みやすくなります。
DVWAの環境構築(3つの方法)
「various versions of DVWA around」とREADMEが注意する通り、非公式の配布物や古いイメージが多数出回っています。公式がサポートするのはGitHubリポジトリの最新ソースだけである点を最初に押さえてください。構築方法は主に次の3系統です。
| 方法 | 向いている人 | 要点 |
|---|---|---|
| 公式Docker | 最短で立てたい | docker compose up -d だけ。DB込みで起動、ポートは4280 |
| Kali Linux | 診断ツールと一緒に使う | kali-linux-labs に同梱、dvwa-start で起動 |
| Windows+XAMPP / Linuxパッケージ |
手動で仕組みを追いたい | Apache+PHP+MariaDBを個別に用意し設定ファイルを編集 |
公式Dockerによる環境構築(推奨)
リポジトリの compose.yml は、DVWA本体(イメージ ghcr.io/digininja/dvwa:latest)とMariaDB 10のコンテナをまとめて起動します。Git・Docker・Docker Composeが使える環境で、リポジトリを取得してディレクトリに入り、次を実行します。
git clone https://github.com/digininja/DVWA.git
cd DVWA
docker compose up -d
起動後は http://localhost:4280 で開きます。コンテナ版が80番でなく4280番を使うのは、80番が使用中の環境やルートレスコンテナ(Podman等)の特権ポート制約を避けるためです。ポート割り当ては compose.yml の 127.0.0.1:4280:80 を書き換えれば変更できます。既定でループバック(127.0.0.1)にのみバインドされるため、そのままなら外部公開されません。
Kali Linux版DVWAの導入と起動
ペネトレーションテスト向けのKali Linuxでは、メタパッケージ kali-linux-labs がDVWAとOWASP Juice Shopを依存として導入します。導入済みなら dvwa-start コマンドでDVWAのサービス(nginx・PHP・MariaDB)が起動し、ブラウザで 127.0.0.1:42001 に admin/password でログインできます。Burp SuiteやOWASP ZAPなど診断ツールと同じ環境で試せるため、攻撃と検出をセットで学ぶ用途に向きます。
Windows/Linuxでの手動構築と必要パッケージ
仕組みを追いたい場合は個別導入もできます。WindowsではApache・MySQL・PHPをまとめたXAMPPが最短です。Debian系Linuxでは apache2・libapache2-mod-php・mariadb-server・mariadb-client・php・php-mysqli・php-gd を導入します。データベースはMySQLでも動きますが、READMEはMariaDBを強く推奨しています。MySQLは接続が通るように手を加える必要がある一方、MariaDBは追加設定なしでそのまま動く(works out of the box)ためです。
PHPのバージョンは開発・テストが行われる最新安定版が前提で、7.3未満は不具合の可能性があり、5.x系はサポート対象外です。PostgreSQLは過去に対応していたものの現在は無効化されており(設定ファイルでも「Currently disabled」)、アプリ本体が使うDBはMySQL系(MariaDB)に一本化されています。なお、SQLインジェクション演習に限っては、設定ファイルの SQLI_DB を SQLITE に切り替えるとSQLite3でも動かせます(既定はMySQL)。
初期設定とログイン(Setup / Reset DB)
手動構築の場合、設定ファイルはひな形 config/config.inc.php.dist を config/config.inc.php にコピーして使います。データベース接続の既定値は次の通りです(Dockerでは環境変数で上書きされます)。
| 設定キー | 既定値 | 意味 |
|---|---|---|
| db_server | 127.0.0.1 | DBのホスト |
| db_database | dvwa | 使用するDB名(セットアップ時に全削除される) |
| db_user | dvwa | DBユーザー(MariaDBではroot不可・専用ユーザーを作る) |
| db_password | p@ssw0rd | DBパスワード |
| default_security_level | impossible | セッション開始時の初期レベル |
アプリを開いたら、メニューの「Setup DVWA」から「Create / Reset Database」を押してテーブルを作成します。完了すると、次の認証情報でログインできます。
Username: admin
Password: password
このユーザーはデモ用の users テーブルに登録された5人のうちの1人で、パスワードはMD5で保存されています。READMEも「簡単に総当たりできる」と添えている通り、後述のBrute Force演習の標的そのものです。ツール連携で認証が邪魔になる場合は、設定ファイルの disable_authentication を true にすると認証なしで各機能へアクセスできます。
セキュリティレベルの4段階
DVWAの学習効果の核心は、メニューのDVWA Securityページで切り替えるセキュリティレベルにあります(レベルを選んでSubmitで反映)。同じ機能でも、レベルによって背後のソースコードが差し替わります。READMEと security.php の定義は次の通りです。
| レベル | 位置づけ | コードの特徴 |
|---|---|---|
| Low | 防御なし | 入力をそのまま使う。攻撃の基本を学ぶ土台 |
| Medium | 不十分な防御 | 対策を試みたが失敗している例 |
| High | 難しい不良実装 | 別方式の不良実装。CTF的に回避を考える |
| Impossible | 安全な実装 | 各演習の脆弱性に対する安全な実装例(比較用の正解コード) |
Impossibleは「脆弱なコードと安全なコードを見比べる」ための正解例で、DVWA v1.9より前は「high」と呼ばれていたレベルです。設定ファイルの初期値はimpossibleなので、演習を始めるときは自分でlowへ下げる必要があります。古い解説記事の「デフォルトはlow」という記述は現行版では誤りなので注意してください。
ソースコードで見るlowとimpossibleの差(SQLインジェクション)
DVWAの真価は、攻撃が通る理由をコードで確認できる点です。SQLインジェクション(vulnerabilities/sqli)を例に、lowとimpossibleの実装を比べます。以下は公式ソース(抜粋元:sqli/source/low.php・sqli/source/impossible.php)から接続処理やエラー処理を省いた抜粋で、そのままの単独実行を意図したものではありません。まずlowは、ユーザー入力 $id をSQL文字列にそのまま埋め込みます。
$id = $_REQUEST['id'];
$query = "SELECT first_name, last_name FROM users WHERE user_id = '$id';";
$result = mysqli_query($GLOBALS["___mysqli_ston"], $query);
入力が文字列連結でクエリに混ざるため、値ではなくSQL構文として解釈されうるのが脆弱性の原因です。一方impossibleは、対策を3つ重ねています。
checkToken($_REQUEST['user_token'], $_SESSION['session_token'], 'index.php');
$id = $_GET['id'];
if(is_numeric($id)) {
$id = intval($id);
$data = $db->prepare('SELECT first_name, last_name FROM users WHERE user_id = (:id) LIMIT 1;');
$data->bindParam(':id', $id, PDO::PARAM_INT);
$data->execute();
}
(1)CSRFトークンの検証、(2)is_numericとintvalによる入力の型チェック、(3)PDOのプリペアドステートメントによる値と構文の分離、が揃っています。中でも決定的なのはプリペアドステートメントで、入力を必ず「値」として扱うため構文として解釈される余地がなくなります。これはIPA「安全なウェブサイトの作り方」1.1 SQLインジェクションが根本的解決として挙げる「プレースホルダで実装する」そのものです。SQLインジェクションの防御原則は認可バイパスやIDORの対策とも共通する「入力を信頼しない」設計思想です。
同じ対比は他モジュールにもあります。コマンドインジェクション(exec)のlowは shell_exec('ping -c 4 ' . $target) と入力を直結しますが、impossibleはIPを4オクテットに分割し各要素を is_numeric で検証してから組み直します。反射型XSS(xss_r)のlowは入力をそのまま出力しますが、impossibleは htmlspecialchars でエスケープします。攻撃と防御が1画面で対になっているのがDVWAの設計です。
impossibleコードとIPA「安全なウェブサイトの作り方」の対応
impossibleレベルの実装は、場当たり的な修正ではなく、公的ガイドラインが示す防御原則と重なります。日本語で学ぶなら、DVWAのソースをIPA「安全なウェブサイトの作り方」の対策項目と照らし合わせて読むと、各impossibleコードがどの防御の考え方に対応するのかを確認できます。主要3モジュールの対応は次の通りです。
| 脆弱性 | DVWA impossibleの実装 | IPAの根本的解決 |
|---|---|---|
| SQLインジェクション | PDOのプリペアドステートメント(値と構文の分離) | 1.1 の 1-(i)-a 全てプレースホルダで実装する |
| 反射型XSS | htmlspecialchars で特殊記号をエスケープ |
1.5 の 5-(i) 全出力要素にエスケープ処理を施す |
| CSRF | Anti-CSRFトークンの照合+現在のパスワード再入力 | 1.6 の 6-(i)-a 秘密情報の照合(考え方)/6-(i)-b パスワード再入力 |
SQLインジェクションとXSSは、impossibleの実装がIPAの根本的解決とそのまま対応します。一方CSRFは注意が必要です。impossibleは、フォームに埋め込んだ user_token をサーバー側で checkToken により照合し、さらに password_current で現在のパスワード一致も確認します(csrf/source/impossible.php)。トークンによる秘密情報の照合はIPAのCSRF対策の「実行ページではその値が正しい場合のみ処理を実行する」考え方に沿い、パスワード再入力は 6-(i)-b に対応します。ただしDVWAのCSRFモジュールはフォームが method="GET" で送信される(csrf/index.php)ため、POST送信を前提とするIPAの 6-(i)-a を丸ごと満たすわけではありません。学習時は「どの対策に対応し、どこが演習ゆえの簡略化か」を区別して読むことが肝心です。XSSとCSRFの違いを押さえておくと、各モジュールの対策がどの攻撃に効くのかを混同せずに追えます。
DVWAで学べる脆弱性モジュール
現行版のメニューには次の演習モジュールが並びます。SQLインジェクション、XSS、CSRF、コマンドインジェクション、ファイルインクルードなど、Webアプリで頻出する脆弱性を実際に試せます。
| モジュール | 学べる脆弱性 |
|---|---|
| Brute Force | ログインの総当たり攻撃 |
| Command Injection | OSコマンドインジェクション |
| CSRF | クロスサイトリクエストフォージェリ |
| File Inclusion | ローカル/リモートファイルインクルード |
| File Upload | 不正ファイルのアップロード |
| Insecure CAPTCHA | CAPTCHA実装の不備 |
| SQL Injection / Blind | SQLインジェクション(通常・ブラインド) |
| Weak Session IDs | 推測可能なセッションID |
| XSS (DOM / Reflected / Stored) | 3種類のクロスサイトスクリプティング |
| CSP Bypass | コンテンツセキュリティポリシーの回避 |
| JavaScript Attacks | クライアント側処理への攻撃 |
| Open HTTP Redirect | オープンリダイレクト |
| Cryptography / API | 暗号の誤用・API脆弱性 |
このほか、adminでログインしたときだけ表示されるAuthorisation Bypass(認可バイパス)があります。APIモジュールを使うにはApacheの mod_rewrite 有効化とComposerによる依存ファイルの導入が、Insecure CAPTCHAにはGoogle reCAPTCHAのキーが別途必要です。XSSやCSRFの違いを整理したい場合はXSSとCSRFの違いを、より広い脆弱性学習ツールと比べたい場合はIPA提供のAppGoatも参考になります。
DVWAの公開禁止と演習用DBの分離
DVWAはREADMEが太字で警告する通り、公開サーバーやホスティングのpublic htmlに置いてはいけません。設置した瞬間に攻撃対象になります。運用の原則は次の3点です。
- ローカル限定で動かす:公式Dockerはデフォルトでループバックにのみバインドされる。手動構築ならNATモードのVM内に閉じる。
- 演習用DBを専用にする:セットアップは指定DBを全削除する。本番や共用のDBを指定しない。
- 用途を守る:学んだ攻撃手法を許可のない対象に試さない。演習は自分の環境やCTFなど合法な場に限る。
DVWAは実際の脅威の入り口を理解する教材であり、防御実装(impossibleレベルのコード)まで見て初めて学習が完結します。攻撃の再現だけで終えず、安全なコードとの差分を必ず確認してください。自社のWebアプリが同種の脆弱性を抱えていないかを客観的に確かめたい場合は、脆弱性診断・セキュリティ診断のように専門の診断で洗い出す選択肢もあります。
よくある質問(FAQ)
DVWAの正式名称と読み方は?
正式名称はDamn Vulnerable Web Applicationで、その頭文字を取った略称です。「ディーブイダブリューエー」と読まれます。
DVWAの初期ログイン情報は?
ユーザー名 admin、パスワード password です。初回はメニューの「Setup DVWA」からデータベースを作成してからログインします。
DVWAのセキュリティレベルの初期値は?
設定ファイルの既定値はimpossible(安全側)です。演習を始めるときは画面のDVWA Securityでlowなどに下げます。古い記事にある「デフォルトはlow」は現行版では当てはまりません。
DVWAをインストールするのに必要な環境は?
手軽さで選ぶなら公式Dockerです。DockerとDocker Composeを入れたうえで、公式リポジトリを git clone してそのディレクトリに移動し、docker compose up -d を実行します。手動構築ではApache・PHP(推奨は最新安定版)・MariaDBを個別に用意します。
DVWAはインターネットに公開してよいですか?
公開してはいけません。意図的に脆弱なため、外部からアクセスできる場所に置くと短時間で侵害される危険があります。ローカル環境やNATモードのVM内だけで利用してください。