Quase todo hacker web tem a mesma história de origem. Alguém mandou instalar o DVWA, a pessoa passou uma noite brigando com um erro de banco de dados e, de repente, uma única aspa simples num campo de texto devolveu cinco registros de usuários e um punhado de hashes de senha. É esse momento que explica por que o Damn Vulnerable Web Application continua sendo o primeiro alvo padrão, quase vinte anos depois de ter surgido.
O DVWA é uma aplicação PHP propositalmente quebrada que você roda na própria máquina e ataca de propósito. Ela cobre a maior parte do OWASP Top 10 num formato que dá para quebrar numa tarde, e mostra o código-fonte vulnerável ao lado de cada desafio. Este guia cobre a instalação, o primeiro login e as soluções dos módulos em que os iniciantes travam. Se você prefere pular a instalação e começar a atacar alguma coisa nos próximos dois minutos, nosso curso de ataques a aplicações web trata das mesmas classes de vulnerabilidade direto no navegador.
Resumo: o DVWA é uma aplicação PHP e MariaDB gratuita e de código aberto, feita para ser hackeada. Rode docker compose up -d no repositório clonado, abra http://localhost:4280, entre com admin / password, clique em Create / Reset Database e ajuste o nível de segurança para Low. Trabalhe cada módulo de Low até Impossible e leia o código-fonte em todos os níveis. Nunca exponha a aplicação à internet.
O que é o DVWA?
O DVWA (Damn Vulnerable Web Application) é uma aplicação web em PHP e MariaDB feita para ser insegura de propósito, para que estudantes, desenvolvedores e testadores de invasão possam praticar ataques reais de forma legal no próprio hardware. Ela foi escrita por Ryan Dewhurst em 2008 e hoje é mantida por Robin Wood (digininja) no GitHub, gratuita e de código aberto sob a GPLv3.
A versão atual é a 2.5, publicada em janeiro de 2025, que acrescentou um módulo de endpoints OpenAPI vulneráveis. O repositório oficial traz 19 módulos de vulnerabilidade: injeção de SQL, injeção de SQL cega, injeção de comandos, XSS refletido, armazenado e baseado em DOM, CSRF, inclusão de arquivos, upload de arquivos, força bruta, IDs de sessão fracos, contorno de autorização, controle de acesso quebrado, contorno de Content Security Policy, lógica JavaScript, redirecionamento aberto, CAPTCHA inseguro, criptografia e o laboratório de APIs.
Duas decisões de projeto fazem dele um material de estudo melhor do que a maioria das aplicações vulneráveis. Primeiro, cada página tem um botão View Source que mostra exatamente o PHP que processa a sua entrada, então você enxerga por que o payload funcionou em vez de adivinhar. Segundo, cada módulo existe em quatro níveis de dificuldade, de forma que a mesma vulnerabilidade ensina o contorno do filtro e depois ensina a correção.
Ele está listado no diretório OWASP de aplicações web vulneráveis e vem empacotado no Kali Linux, o que é um sinal razoável de que se trata do padrão da comunidade e não de um projeto qualquer no GitHub.
Como instalar o DVWA com Docker
Docker é a escolha certa para a primeira instalação. O caminho manual significa instalar Apache, PHP e MariaDB, editar o php.ini, corrigir permissões de pasta e depois depurar o que a sua distribuição fez de diferente. O caminho do contêiner são quatro comandos.
- Verifique se o Docker está presente. Rode
docker versionedocker compose version. Os dois precisam devolver um número de versão. O Docker Desktop já inclui o Compose; no Linux, instale o Docker Engine pelo repositório oficial em vez do gerenciador de pacotes, que costuma trazer um Compose mais antigo. - Clone o repositório.
git clone https://github.com/digininja/DVWA.gite depoiscd DVWA. Use o repositório oficial. Os espelhos que circulam no SourceForge e no Docker Hub estão anos atrasados e sem vários módulos. - Suba a aplicação.
docker compose up -d. A primeira execução baixa a imagem pré-construída do GitHub Container Registry e leva um ou dois minutos. - Abra no navegador. Acesse
http://localhost:4280. O contêiner escuta na porta 4280, não na 80, que é de longe o motivo mais comum de as pessoas acharem que a instalação falhou.
No Kali, sudo apt install dvwa instala a versão empacotada, documentada na página de ferramentas do Kali. Funciona, mas fica atrás da versão do GitHub, então podem faltar os módulos mais novos. Para instalar à mão no Debian ou no Ubuntu você precisa de apache2, libapache2-mod-php, mariadb-server, mariadb-client, php, php-mysqli e php-gd, com o PHP 7.3 como mínimo absoluto.
Não rode o DVWA num servidor público. O README do projeto é direto: coloque isso num host exposto à internet e ele será comprometido. Mantenha em localhost ou dentro de uma VM com rede em modo NAT. Um contêiner Docker não é uma fronteira de segurança aqui, é uma conveniência.
Primeiro login e criação do banco
A tela de login pede credenciais antes de você ter criado alguma. O login padrão do DVWA é o usuário admin com a senha password. O README observa, com humor evidente, que essas credenciais caem facilmente em força bruta. Isso não é acidente, é o módulo Brute Force dando uma piscadela para si mesmo.
Assim que entrar, a aplicação vai reclamar que o banco de dados não existe. Clique em Setup DVWA no menu da esquerda, role até o fim da página e clique em Create / Reset Database. Você é desconectado, entra de novo, e os cinco usuários de exemplo já estão lá. Volte a esse botão sempre que um módulo começar a se comportar de forma estranha, porque metade das perguntas do tipo "o DVWA quebrou" nos fóruns se resolve reiniciando o banco.
A página de setup também confere a sua configuração do PHP. Duas entradas importam desde cedo:
allow_url_includeprecisa estar ligado para a parte de Remote File Inclusion do módulo de inclusão de arquivos. Na imagem Docker já está. Numa instalação manual você vai editar o/etc/php/8.x/apache2/php.inie reiniciar o Apache.- Chaves do reCAPTCHA só são necessárias para o módulo Insecure CAPTCHA. Pule esse módulo por enquanto e ignore o aviso. É o único laboratório que exige uma conta externa, e ensina menos que os outros.
Na prática, a maneira mais rápida de perder uma hora numa instalação nova é a pasta de upload sem permissão de escrita. O módulo File Upload grava em ./hackable/uploads/, e se o usuário do servidor web não puder escrever ali, os uploads falham em silêncio de um jeito que parece um filtro bloqueando você. A imagem Docker resolve isso. Uma instalação manual, nem sempre.
Os quatro níveis de segurança são o verdadeiro currículo
A página Security do DVWA deixa você escolher entre Low, Medium, High e Impossible, e é aí que a maioria dos iniciantes desperdiça a ferramenta. Colocam em Low, resolvem dez módulos numa noite e concluem que sabem hackear web. Low é um tutorial, não um laboratório.
| Nível | O que o código faz | O que você aprende |
|---|---|---|
| Low | Nenhum tratamento de entrada | O formato bruto da vulnerabilidade |
| Medium | Uma lista negra ingênua ou uma checagem no cliente | Por que listas negras perdem |
| High | Uma lista negra maior, com uma brecha dentro | Teste de filtro paciente e metódico |
| Impossible | A defesa correta, e ela aguenta | Como é um código seguro |
Impossible é o nível que todo mundo ignora, e é o que torna você empregável. Lê-lo depois de ter quebrado os outros três é o mais perto que existe de uma aula gratuita de desenvolvimento seguro. Um relatório que diz "você está vulnerável a injeção de SQL" vale alguma coisa. Um relatório que mostra a consulta parametrizada que corrige o problema vale bem mais.
Solução: injeção de SQL de Low a Impossible
O módulo SQL Injection oferece um campo que recebe um User ID e devolve um nome. Em Low, o código-fonte é uma única linha de concatenação de strings:
$query = "SELECT first_name, last_name FROM users WHERE user_id = '$id';";
Sua entrada cai dentro de aspas simples sem nenhum escape, então o primeiro trabalho é sair da aspa. Digite 1' OR '1'='1 e a condição passa a ser sempre verdadeira, devolvendo os cinco usuários em vez de um. Essa é a sua prova de que o ponto de injeção existe.
Agora torne isso útil. A consulta devolve duas colunas, então um UNION também precisa devolver duas colunas:
1' UNION SELECT user, password FROM users#
A saída agora lista cada nome de usuário ao lado de um hash MD5 da senha. O # no fim comenta o resto da consulta original, incluindo a aspa de fechamento. Se quiser a teoria por trás da exigência de igualar a contagem de colunas, nosso tutorial de injeção de SQL percorre os ataques UNION passo a passo.
Vá para Medium e o campo de texto vira uma lista suspensa. Essa é uma restrição do lado do cliente, o que significa que não é restrição nenhuma. Intercepte a requisição num proxy, ou simplesmente reenvie com o parâmetro id alterado, e você está de volta ao jogo. O nível Medium também passa a usar mysqli_real_escape_string e remove as aspas ao redor do valor, então o payload muda de forma: não há aspa para escapar, e 1 OR 1=1 funciona direto.
Depois leia o Impossible, que é o verdadeiro objetivo do exercício:
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();
}
Quatro defesas empilhadas: checagem de tipo, conversão para inteiro, consulta preparada com parâmetro vinculado e limite de linhas. Há ainda um token anti-CSRF no formulário. Nada do que você digita chega ao analisador SQL como código, e é por isso que nenhum payload funciona e por isso que esse é o padrão a copiar.
Solução: injeção de comandos, XSS e upload de arquivos
Esses três módulos são os que constroem a reputação do DVWA, porque cada um tem um nível Medium ou High com uma brecha de filtro realmente instrutiva.
Injeção de comandos
A página faz ping no endereço IP que você informa. Em Low, o código é shell_exec( 'ping -c 4 ' . $target ), então tudo o que você acrescentar roda no host. Tente 127.0.0.1; whoami e a saída do ping chega com www-data logo abaixo.
O Medium acrescenta uma lista negra que apaga && e ; da sua entrada. São dois separadores de shell removidos de pelo menos cinco. Um pipe continua funcionando:
127.0.0.1 | whoami
O High estende a lista negra para ||, &, ;, -, $, (, ), crase, e | seguido de espaço. Releia essa última entrada. O filtro remove o pipe com espaço depois, e deixa o pipe sozinho em paz. Então 127.0.0.1|whoami passa direto.
Esse único caractere é a lição mais valiosa de toda a aplicação. Listas negras falham no caso que o autor não imaginou, e encontrar esse caso é o trabalho. A referência da OWASP sobre injeção de comandos lista os separadores que vale testar de forma sistemática em vez de no chute.
XSS refletido
Em Low, o parâmetro name é ecoado direto na página, então <script>alert(1)</script> dispara na hora. O Medium é mais interessante. O filtro é este:
$name = str_replace( '<script>', '', $_GET[ 'name' ] );
Uma string, removida uma vez, e que diferencia maiúsculas de minúsculas. Três formas diferentes de passar, e cada uma ensina um hábito distinto. Troque as maiúsculas com <SCRIPT>alert(1)</SCRIPT>. Aninhe a tag para que a remoção da interna reconstrua a externa, usando <scr<script>ipt>alert(1)</script>. Ou evite a palavra por completo com <img src=x onerror=alert(1)>, o payload que continua funcionando muito depois de os outros dois pararem.
Upload de arquivos
O Low aceita qualquer arquivo e o deposita em hackable/uploads/. Envie um arquivo PHP pequeno que execute um comando vindo de um parâmetro de URL, acesse o caminho que a página devolve, e você tem execução de código.
O Medium confere duas coisas: se o tamanho é menor que 100000 bytes e se o tipo MIME é image/jpeg ou image/png. O tamanho é real. O tipo MIME não, porque vem do cabeçalho Content-Type que o seu navegador envia e que você controla por completo. Intercepte o upload, troque Content-Type: application/x-php por Content-Type: image/jpeg, encaminhe, e o arquivo PHP chega intacto. Nosso tutorial do Burp Suite cobre o fluxo de interceptar e modificar caso você ainda não tenha configurado um proxy.
A regra geral que esse módulo ensina: qualquer valor que o cliente envia é uma sugestão, nunca um fato. Nome do arquivo, extensão, Content-Type, campos ocultos de formulário, cookies. Tudo isso é controlado pelo atacante.
Os módulos que os iniciantes pulam
Todo mundo faz injeção de SQL e XSS. Três módulos ficam de fora, e são justamente os que mais se aproximam de trabalho remunerado.
- Injeção de SQL cega. Mesma vulnerabilidade, sem mensagens de erro e sem saída visível. Você confirma com uma condição booleana ou um atraso de tempo e extrai os dados um caractere por vez. Mais lento, menos gratificante e muito mais próximo da cara que as aplicações reais têm quando o relatório de erros está desligado em produção.
- IDs de sessão fracos. Clique no botão, observe o cookie, repare que ele é incrementado de um em um. Identificadores de sessão previsíveis permitem virar outro usuário sem tocar na senha dele. São dez minutos e mudam a forma como você olha para qualquer cookie daí em diante.
- Inclusão de arquivos. No Medium o filtro remove
../e..\uma única vez, então....//se recompõe em../depois da substituição. Ele também removehttp://, o quehthttp://tp://derruba pelo mesmo motivo. Duplicar o seu payload para sobreviver a um filtro de passagem única é um padrão que você vai reutilizar o tempo todo.
Um hábito prático que vale adotar: depois de resolver um módulo em Low, não pule para o módulo seguinte. Vá para o Medium do mesmo módulo. Profundidade numa única classe de vulnerabilidade vence largura em dez, ainda mais quando o código-fonte da correção está a um clique.
O que o DVWA não vai te ensinar
O DVWA é excelente em uma tarefa e mediano em várias outras. Ser honesto sobre essa diferença evita o platô que trava muita gente autodidata.
Não existe fase de reconhecimento. Toda vulnerabilidade vem etiquetada, num menu, com um botão. Um teste de verdade começa com um domínio e muita incerteza, e encontrar o parâmetro vulnerável é a maior parte do trabalho. O DVWA entrega esse parâmetro de graça.
A pilha é datada. É PHP renderizado no servidor, com query strings e envios de formulário. Isso ensina os fundamentos de forma honesta, e os fundamentos continuam valendo. Não ensina nada sobre um front end React conversando com uma API JSON, sobre JWT, GraphQL ou sobre as falhas de lógica de autorização que dominam os relatórios modernos de bug bounty.
Nada reage contra você. Sem limite de requisições, sem WAF, sem registro de log, sem bloqueio de conta. Útil enquanto você aprende o payload. Enganoso quanto à sensação real de um trabalho de campo.
Nada disso faz dele um primeiro alvo ruim. Faz dele um primeiro alvo. Use para aprender como cada classe de vulnerabilidade se comporta por dentro e depois vá para ambientes em que é preciso encontrar a falha antes de explorá-la. OWASP Juice Shop, uma plataforma de laboratórios hospedada ou um programa de bug bounty real são próximos passos razoáveis.
Considerações legais e éticas
Lembrete crítico: sempre obtenha autorização escrita e explícita antes de testar qualquer sistema. O DVWA na sua própria máquina está autorizado por definição. Todo o resto exige permissão por escrito, e o fato de uma técnica ter funcionado num laboratório nunca serve de defesa.
- Mantenha tudo local. Prenda a aplicação ao localhost ou a uma VM em modo NAT. Um DVWA exposto é uma porta dos fundos funcional para a sua própria rede, e scanners automatizados encontram uma dessas em poucas horas.
- Não reutilize os payloads sem pensar. Digitar
1' OR '1'='1num formulário de login que não é seu configura invasão de dispositivo informático pelo artigo 154-A do Código Penal brasileiro, pelo Computer Misuse Act no Reino Unido, pelo CFAA nos Estados Unidos e por leis equivalentes em quase todo lugar. - Programas de bug bounty são o caminho legal. Eles dão permissão por escrito e um escopo definido. Leia o escopo antes de testar, não depois.
- Reporte o que encontrar de forma responsável. Se topar com uma vulnerabilidade real fora de um programa, avise o dono e pare de testar. Não extraia dados para provar o seu ponto.
Perguntas frequentes
Qual é o login padrão do DVWA?
O usuário padrão é admin e a senha padrão é password. Se o login falhar numa instalação nova, é porque o banco de dados ainda não foi criado: entre, clique em Setup DVWA no menu da esquerda e clique em Create / Reset Database no fim da página.
Em que porta o DVWA roda no Docker?
Na porta 4280, não na 80. Depois de docker compose up -d a aplicação fica em http://localhost:4280. Isso difere da instalação manual com Apache, em que ela ocupa a porta 80 em http://127.0.0.1/DVWA, e é o motivo mais comum de uma instalação Docker parecer quebrada.
É seguro instalar o DVWA?
É seguro numa máquina que você controla, em localhost ou numa VM com rede em modo NAT. Não é seguro em nenhum servidor exposto à internet. A aplicação é intencionalmente vulnerável a execução remota de código, então expô-la publicamente entrega um shell naquele host a um atacante.
Quantas vulnerabilidades o DVWA tem?
A versão 2.5 traz 19 módulos, incluindo injeção de SQL, injeção de SQL cega, injeção de comandos, três tipos de XSS, CSRF, inclusão de arquivos, upload de arquivos, força bruta, IDs de sessão fracos, contorno de CSP, redirecionamento aberto, criptografia e APIs vulneráveis. A documentação também informa que há vulnerabilidades não documentadas no código, deixadas de propósito para você encontrar.
O DVWA ainda vale a pena em 2026?
Vale, para o primeiro mês de segurança web. Suas classes de vulnerabilidade continuam no OWASP Top 10 e o recurso View Source ensina a causa raiz melhor do que a maioria dos cursos pagos. Siga em frente assim que conseguir fechar o nível High sozinho, porque ele não cobre APIs, JWT nem aplicações JavaScript modernas.
Qual é a diferença entre DVWA e OWASP Juice Shop?
O DVWA é PHP com um menu de vulnerabilidades etiquetadas e código-fonte visível, o que o torna melhor para entender a causa raiz. O Juice Shop é uma aplicação JavaScript de página única moderna em que os desafios ficam escondidos e você precisa encontrá-los, o que o torna melhor treino para descoberta realista. Faça o DVWA primeiro, o Juice Shop depois.
Seus próximos passos
O ciclo do DVWA que realmente constrói habilidade é curto: instale com Docker, reinicie o banco, ajuste o nível para Low, resolva o módulo, leia o código-fonte e então leve o mesmo módulo para Medium e High antes de seguir adiante. Termine lendo o nível Impossible, porque conhecer a correção é o que transforma um hobby em profissão.
A única coisa que uma instalação local não consegue oferecer é a pressão de um alvo que você precisa decifrar sozinho. Experimente o Query Quake para injeção de SQL ou o Ping Pwn para injeção de comandos, os dois rodando no navegador, sem nada para instalar. Nosso curso de ataques a aplicações web percorre cada classe de vulnerabilidade em ordem, e o plano gratuito da HackerDNA não pede cartão de crédito para começar.
Faz parte da série OWASP Top 10
Artigos relacionados: