
Ansible role deploying a vulnerable CrushFTP 10.8.0 instance on Windows for authorized penetration testing of CVE-2025-31161 authentication bypass.
An Ansible Role that deploys a vulnerable CrushFTP 10.8.0 instance on Windows for authorized penetration testing of CVE-2025-31161 (authentication bypass).
The vulnerable CrushFTP binary is hosted at rufflabs/crushftp_cve-2025-31161 and downloaded automatically at deploy time. If that repo is unavailable, the role falls back to pulling directly from Docker Hub.
[!WARNING] This role deploys an intentionally vulnerable application. Use only in isolated lab environments. Do not expose to untrusted networks.
api.adoptium.net on first deploy (files are cached after that).Available variables are listed below, along with default values (see defaults/main.yml):
# GitHub Release URL for the vulnerable CrushFTP build
ludus_crushftp_download_url: "https://github.com/rufflabs/crushftp_cve-2025-31161/releases/download/v10.8.0_4/CrushFTP10_10.8.0_4.zip"
# Fall back to Docker Hub if GitHub download fails
ludus_crushftp_fallback_to_docker: true
# Installation path on the Windows target
ludus_crushftp_install_dir: "C:\\CrushFTP"
# Admin account (default exploit target for CVE-2025-31161)
ludus_crushftp_admin_user: "crushadmin"
ludus_crushftp_admin_password: "CrushAdmin123!"
# Windows service settings
ludus_crushftp_service_name: "CrushFTP"
ludus_crushftp_service_start_mode: auto
# Network ports
ludus_crushftp_http_port: 8080
ludus_crushftp_https_port: 443
# Create Windows Firewall allow rules
ludus_crushftp_configure_firewall: true
None.
ludus:
- vm_name: "{{ range_id }}-crushftp"
hostname: "{{ range_id }}-CRUSH"
template: win2022-server-x64-template
vlan: 20
ip_last_octet: 10
ram_gb: 4
cpus: 2
windows:
sysprep: true
roles:
- rufflabs.ludus_crushftp_cve_2025_31161
role_vars:
ludus_crushftp_admin_user: "crushadmin"
ludus_crushftp_admin_password: "CrushAdmin123!"
# Add the role
ludus ansible role add rufflabs.ludus_crushftp_cve_2025_31161
# Update your range config
ludus range config get > config.yml
# Edit config.yml to add the role (see example above)
ludus range config set -f config.yml
# Deploy (role only, if range is already up)
ludus range deploy -t user-defined-roles
- hosts: crushftp_hosts
roles:
- rufflabs.ludus_crushftp_cve_2025_31161
Once deployed, test from your attack VM:
# Nuclei detection
nuclei -u http://<target-ip>:8080 -t CVE-2025-2825.yaml
# Immersive Labs PoC (creates a backdoor admin account)
python3 cve-2025-31161.py \
--target_host http://<target-ip>:8080 \
--target_user crushadmin \
--new_user backdoor \
--password backdoor123
CrushFTP10_10.8.0_4.zip from rufflabs/crushftp_cve-2025-31161 GitHub Releases (falls back to Docker Hub registry API if unavailable). Downloads Adoptium JDK 21. Both cached on the Ludus host at /opt/ludus/resources/crushftp/.crushadmin account, installs the Windows service, sets JAVA_HOME, and opens firewall ports.| Repository | Purpose |
|---|---|
| rufflabs/crushftp_cve-2025-31161 | Hosts the vulnerable CrushFTP binary as a GitHub Release asset |
| rufflabs/ludus_crushftp_cve-2025-31161 | This role — Ansible/Ludus automation for deployment |
MIT