Skip to content

Back to the catalog

DVLAA
github.comrepo

DVLAA

DVLAA (Damn Vulnerable LLM and Agent Application) is a self-hosted, Docker-deployable security training range for LLM and agent applications, modeled on the DVWA concept but for AI. It covers OWASP LLM Top 10 and Agent Security Top 10 risks (prompt injection, RAG poisoning, tool abuse, memory poisoning, excessive resource consumption, etc.) through 81 hands-on challenges, including an "AWDP" attack/defense track where 10 challenges reproduce real disclosed vulnerabilities in Dify, RAGFlow, Langflow, Flowise, Open WebUI and n8n (with optional real upstream container reproduction), 20 challenges adapted from a China–ASEAN AI security CTF, and 6 challenges adapted from a real model-poisoning CTF. It provides real model interaction, state-machine flag verification, source/prompt viewers, model management (local, Ollama, SiliconFlow, OpenAI-compatible), and bilingual UI.

TL;DR Self-hosted "DVWA for LLMs/agents": 81 challenges spanning OWASP LLM/Agent Top 10 plus real-CVE attack/defense drills against Dify, RAGFlow, Langflow, Flowise, Open WebUI and n8n.
Document

What it is

DVLAA is a self-hosted Flask training range for LLM/agent security. The summary covers the challenge counts and topic coverage; what it omits is the defend-side mechanism of the AWDP track and the concrete deployment/operational details an engineer needs to judge whether it fits their environment.

How the AWDP defense track actually works

This is the part that distinguishes DVLAA from a pure attack range. Each of the 30 AWDP challenges has an attack phase and a patch-verification phase:

  • Attack side submits real requests through a business Web/API window. A submission is only accepted when the vulnerable server's JSON response actually returns the current session Flag — no keyword or front-end-state faking.
  • Defend side downloads auditable source, edits the flagged server file (e.g. src/web_service.js), and uploads a patch as a .tar.gz/.tgz containing update.sh plus patched files.
  • The platform does not execute arbitrary shell. update.sh may keep shebang, comments, and set -e/set -eu/set -euo pipefail, but only whitelisted cp/mv/rm file operations are interpreted.
  • Verification is two-stage: a static server-side contract check (varies by language field — Python does syntax-compile + vulnerable-clause removal + semantic preservation; text/JS is marker-checked; JS-QuickJS covers AWDP01-10), then dual regression — the vulnerable request must be blocked and normal business functions must still work. Any failure keeps the original deployment.

AWDP11-20 share one pattern: "untrusted text wording substituting for server-side authorization"; the fix is to remove the legacy decision branch and restore server-side authorization as the sole judgment source.

flowchart TD
    P[Upload patch .tar.gz + update.sh] --> W{Whitelisted<br/>cp/mv/rm only?}
    W -->|no| REJ[Rejected]
    W -->|yes| SC{Static contract<br/>check passes?}
    SC -->|no| KEEP[Keep original deployment]
    SC -->|yes| VR{Vuln blocked AND<br/>business still works?}
    VR -->|no| KEEP
    VR -->|yes| PASS[Patch accepted]

The two AWDP tracks

  • Simulation track (default): product-facsimile web apps (Dify/RAGFlow skins) served by integrations/targets/target_server.py, state in integrations/targets/runtime/<id>.json. Zero dependencies, session-dynamic Flags.
  • Real-reproduction track (on demand): clicking "启动真实复现环境" has env_orchestrator pull official container groups (e.g. Dify 1.9.2 full stack) via Docker; the workbench iframe swaps to the real app. Same Flag/patch/regression logic applies to both. AWDP01-10 map disclosed CVEs; CVE/NVD/GHSA are used only to explain root cause — Flags and attack chains are locally generated, never touching upstream.

Real-CTF poisoning track (6 of 10 imported)

REAL01-04 and REAL06 are read-only artifact-forensics tasks (signed adapter manifests/ledgers, challenge.pt/challenge.pth tensor inspection, gradient-print fingerprint recovery, LoRA merge-gate bypass) — the platform does not deserialize pickles or execute attachment content; players work in a read-only materials pane. REAL05 (Hidden_Margin) is the only full-source web challenge, with its own Northstar-clone environment at /real-web/5/.

Deploying it

git clone https://github.com/Tcotl/DVLAA.git
cd DVLAA
./install.sh

install.sh creates the dvlaa-net network, builds the image, starts the AWDP simulation targets and the nginx 5080 single-port gateway, and waits on /health. All vulnerable environments are exposed only through port 5080 (localhost → console, awdpNN.localhost → target vhost). Override the port with DVLAA_PORT=5081 ./install.sh.

Requirements: Python 3.11+, Docker 24.0+, minimum 4GB RAM (8GB+ recommended); the real Dify reproduction stack wants 16GB.

Default credentials ship built-in; override at deploy time:

DVLAA_ADMIN_USERNAME=admin \
DVLAA_ADMIN_PASSWORD='DVLAA2026+' \
./install.sh

Model backends (local, Ollama via OLLAMA_BASE_URL, SiliconFlow via SILICONFLOW_API_KEY, OpenAI-compatible) are configured in the model-management console; keys are stored in data/ or the dvlaa-data volume and shown masked.

Caveats

The page flags that some AWDP cases have no upstream fix yet (explicitly labeled). AWDP21's attachment is only an entry hint requiring equivalent source completion; AWDP30 is a reconstructed teaching copy built from a solver's work-in-progress archive, not the original challenge — so those two are adaptations rather than faithful reproductions.

Technologies named here

Techniques named here

  • 提示词注入
  • 敏感信息泄露
  • RAG 投毒
  • 工具滥用
  • 权限边界突破
  • 记忆污染
  • 输出处理风险
  • 资源消耗攻击
  • 目标劫持
  • 身份权限滥用
  • 供应链风险
  • 代码执行
  • 多智能体通信滥用
  • 级联故障
  • 人机信任滥用
  • 失控智能体
  • 越权数据暴露
  • 不可信文本措辞替代服务端授权
  • tool_call 注入越权读取内部文档
  • guest 导入接受审核字段导致知识库投毒
  • LoRA 合并门控绕过
  • 预处理指纹与 gradient print 泄露调试凭据
  • 模型工件取证
  • 签名 release adapter 取证