Open-source project
digininja/DVWA avatar
digininja/DVWA

DVWA: a deliberately vulnerable PHP app for practising web exploits

Damn Vulnerable Web Application (DVWA)

13,741 stars5,142 forksPHPGPL-3.0

At a glance

What is it?
Damn Vulnerable Web Application is a PHP and MariaDB target with graded difficulty, a Docker path and a GPL-3.0 licence. It is a training ground, not a scanner, and it must never face the internet.
Who is it for?
Adopt DVWA if you are learning web exploitation, teaching a class, or validating a scanner against known-vulnerable endpoints, and run it on a NAT-mode virtual machine or the loopback-bound Docker service. Do not adopt it as a production component, a hardened test harness, or anything reachable from a public address: the README states plainly that an internet-facing install will be compromised.
Can I use it commercially?
Yes, with conditions. GPL-3.0 is a copyleft licence: if you distribute software that includes it, you must release that software's source code under the same licence. Running it internally without distributing it does not trigger that obligation.
Is it still maintained?
Yes. The repository last received commits 23 days ago.
What is it written in?
Mainly PHP, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on September 29, 2026, and from our analysis. They are not legal advice.

Editorial analysis

What DVWA is, and who it is actually for

DVWA is a PHP and MariaDB web application whose stated goal is to be an aid for security professionals testing their skills and tools in a legal environment, for web developers learning how applications are secured, and for students and teachers working in a controlled classroom. That sentence covers the whole intended audience, and it is narrower than the project's popularity suggests.

The design decision that defines it is deliberate vulnerability. The README notes there are both documented and undocumented vulnerabilities, and that this is intentional: you are encouraged to try and discover as many issues as possible. So DVWA is not a checklist of labelled bugs with an answer key. It is a target you are meant to attack with your own tooling, and the difficulty setting is the dial that controls how much help the application gives you.

If you want a scanner benchmark with reproducible ground truth, this is a slightly awkward fit, because the undocumented issues mean your scan results will never line up neatly with a published list. If you want a place to break things and learn why they broke, it is close to ideal. The distinction matters before you install anything.

How the vulnerability modules and difficulty levels fit together

The repository layout shows the shape of the thing. There is a vulnerabilities/ directory holding the exercise modules, a config/ directory, a database/ directory, a dvwa/ directory, a hackable/ directory, and a tests/ directory. The topics attached to the repository name the categories explicitly: sql-injection among them, alongside the broader security and training tags.

Release 2.5, dated 2025-01-29, is titled Vulnerable APIs. Before that, 2.4 in September 2024 added a cryptography module, and 2.3 in June 2023 added container support. That progression is informative: the project keeps adding new classes of exercise rather than polishing the old ones, so the surface a learner can practise against keeps widening.

The difficulty levels are the mechanism that makes one codebase serve both a beginner and someone who already writes exploits. At the low end the application is helpful, and at the high end it is not. The README does not spell out the per-level behaviour of each module, so the practical way to understand the grading is to read the module source under vulnerabilities/ and compare levels yourself. That reading is part of the exercise, not a workaround.

Installing DVWA with Docker on a loopback port

The repository ships a compose.yml that builds a local image or pulls a prebuilt one from GitHub Container Registry, and pairs it with MariaDB 10. The service publishes port 4280 on the host, bound to 127.0.0.1, which maps to port 80 inside the container. The database service sets MYSQL_DATABASE and MYSQL_USER both to dvwa and MYSQL_ROOT_PASSWORD to dvwa.

bash
git clone https://github.com/digininja/DVWA.git
cd DVWA
docker compose up -d

The README also offers a ZIP of the files from the repository archive if you would rather not use git. After the containers come up, the application is reachable at the loopback address on port 4280. Because the port binding is 127.0.0.1, the stack is not exposed to your network by default, and that binding is worth preserving rather than editing.

The compose file sets pull_policy to always, with a comment saying to change it to build to build from local source. There are also two commented volume lines that would serve your local checkout at /var/www/html if you uncomment them, which is what you want when you are editing module code and want the changes reflected without a rebuild.

Finishing setup and a first SQL injection attempt

DVWA does not work immediately after the containers start. There is a setup.php entry point in the repository root, and the Dockerfile copies config/config.inc.php.dist to config/config.inc.php during the image build, so a container install arrives with a configuration file already in place. For a source install you copy that file yourself and edit the database credentials to match your server.

The Dockerfile installs the mysqli, pdo and pdo_mysql extensions along with gd, and it runs composer install inside vulnerabilities/api to set up the API module that arrived in release 2.5. It also enables Apache rewrite.

Once you can reach the login page, the README states the automated install script leaves the credentials ready for login as admin with the password password. Change that before you do anything else, then open setup.php and let it create the database tables. The setup page reports whether the database is reachable and whether the tables were created; if it fails, the usual cause is credentials in config/config.inc.php that do not match the database service.

With setup complete, log in, pick a difficulty level on the security page, and open the SQL injection module. Submit a value that makes the query behave differently from a plain lookup, and read the response. Then open the module source under vulnerabilities/ and compare it against the level you selected. Getting the injection to work is the easy half; explaining which line of PHP made it possible is the part that transfers to real code.

The exposure problem is the point, and it is also the risk

The README's warning is unusually blunt: do not upload DVWA to a hosting provider's public html folder or any internet-facing server, because they will be compromised. It recommends a virtual machine such as VirtualBox or VMware set to NAT networking mode, with XAMPP inside the guest for the web server and database. The disclaimer adds that the authors take no responsibility if a web server is compromised through an installation of DVWA.

That is not boilerplate. A deliberately vulnerable application with a known default credential and a documented SQL injection endpoint is a remote shell waiting to happen, and the project's own documentation says so. The Docker compose file's 127.0.0.1 binding is the same judgement expressed in configuration.

The second limitation is less obvious. Because the application is intentionally broken, you cannot use it to validate that your hardening works. A passing scan against DVWA tells you your scanner detects things; it tells you nothing about whether your own application is safe, because DVWA is not built to be safe. Teams sometimes reach for it as a staging target and then misread the results. It is a practice dummy, not a control.

How DVWA differs from a general-purpose vulnerable target

The obvious alternative in this space is OWASP Juice Shop, which is a Node.js application with a modern single-page front end and a built-in scoreboard that tracks which challenges you have solved. The difference in approach is the feedback loop. Juice Shop tells you when you have found something. DVWA, by design, does not, because it deliberately includes undocumented vulnerabilities and expects you to discover issues rather than tick them off.

That makes the two tools suit different learners. If you are new to web security and need confirmation that you are on the right track, a scoreboard removes a lot of the guesswork. If you already know the classes of bug and want a target where the difficulty levels let you strip away the hints, DVWA's silence is the feature.

The other practical difference is the stack. DVWA is PHP, Apache and MariaDB, which is exactly the combination behind a large amount of legacy web software. Practising against PHP and MySQL specifically is more transferable to that world than practising against a JavaScript stack. The trade-off is that you inherit PHP-era patterns and none of the modern front-end attack surface.

Maintenance, licence and the cost of upgrading

The repository is not archived, and the last push was on 2026-09-07, so the project is still receiving changes. Releases arrive roughly annually: 2.3 in June 2023, 2.4 in September 2024, 2.5 in January 2025. Each has added a module or a deployment path rather than reworking the core, which keeps upgrade risk low but also means the older modules are not being revisited.

DVWA is licensed GPL-3.0, and the Dockerfile carries the org.opencontainers.image.licenses label set to gpl-3.0. In practice that means if you fork the application and distribute your modified version, the licence's copyleft terms apply to what you distribute. Running it locally for training, or inside a company lab, is the ordinary use the project anticipates. This is a description of the licence text, not legal advice; check the GPL-3.0 terms if you plan to redistribute a modified build.

The upgrade cost is mostly in the database and configuration. Because the Dockerfile copies config.inc.php.dist into place at build time, a container upgrade can overwrite local configuration, and the README does not document a rollback path for the setup step. If you have customised config/config.inc.php inside a container, keep the original outside the image before you pull a newer tag.

Editorial conclusion

Adopt DVWA if you are learning web exploitation, teaching a class, or validating a scanner against known-vulnerable endpoints, and run it on a NAT-mode virtual machine or the loopback-bound Docker service. Do not adopt it as a production component, a hardened test harness, or anything reachable from a public address: the README states plainly that an internet-facing install will be compromised. Before you start, verify three things: that you have cloned the official repository rather than a mirror, that config/config.inc.php points at a database you are willing to destroy, and that port 4280 in compose.yml is bound to 127.0.0.1 and not 0.0.0.0. If you cannot confirm all three, run it on a disposable guest instead.

Frequently asked questions

What is the purpose of DVWA?

DVWA is a deliberately vulnerable PHP and MariaDB web application built to help security professionals test their skills and tools in a legal environment, help web developers understand how applications are secured, and support students and teachers in a controlled classroom. It aims to let you practise common web vulnerabilities at various levels of difficulty through a simple interface.

How to setup DVWA?

Clone the official repository, start the stack, then open setup.php to create the database tables. The README gives git clone https://github.com/digininja/DVWA.git as the download step, and the bundled compose.yml runs the application on 127.0.0.1:4280 with a MariaDB 10 service. The README states the automated install script leaves the admin login ready with the password password.

Can I run DVWA with Docker instead of XAMPP?

Yes. The repository includes a compose.yml that builds the image or pulls ghcr.io/digininja/dvwa:latest, and the README notes that every commit to the master branch causes a Docker image to be built and published to GitHub Container Registry. The Dockerfile is based on php:8-apache and installs the mysqli, pdo and pdo_mysql extensions.

What are the default DVWA login credentials?

The README states the automated installation script initialises the database tables ready for login as admin with the password password. Change that credential before using the instance for anything, since the application is intentionally vulnerable.

Why does DVWA warn against installing on a public server?

The README warns that DVWA is damn vulnerable and that uploading it to a hosting provider's public html folder or any internet-facing server will result in compromise. It recommends a virtual machine set to NAT networking mode instead.

Official sources

  1. digininja/DVWA on GitHub
  2. Issues
  3. License: GPL-3.0
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/digininja-dvwa.svg)](https://hysenlabs.com/projects/digininja-dvwa)