Skip to content
KitploitKITPLOIT
ToolsBlog
Submit
ToolsBlog
Submit

Hacking, PenTest, and Cybersecurity Tools for Your Security Arsenal!

Kitploit is a directory of hacking, cybersecurity, and pentesting tools. Discover the latest project updates to find vulnerabilities, analyze systems, automate testing, and strengthen your security.

··Feeds·Contact·Privacy·© 2026 Kitploit

Tool Directory

Categories

View all categories
Loading categories
cve-2015-3306-lab — Reproducible Docker lab + raw-socket exploit for CVE-2015-3306 (ProFTPD mod_copy pre-auth arbitrary file copy) — a patch-diffing learning exercise | Kitploit
Tools/GitHubGitHub/diegslva/cve-2015-3306-lab
Exploit FrameworksVulnerability AnalysisExploitationWeb Application ExploitationPenetration TestingLearning & EducationLabs & Practice
GitHubdiegslva/cve-2015-3306-lab

cve-2015-3306-lab

Reproducible Docker lab + raw-socket exploit for CVE-2015-3306 (ProFTPD mod_copy pre-auth arbitrary file copy) — a patch-diffing learning exercise

View Repository
8h 57m agoNot yet reviewed

Most Popular

View all →

Discover the most used tools by our community.

Explore all tools

Browse our collection of tools

View all tools →
Share

CVE-2015-3306 — ProFTPD mod_copy Pre-Auth Arbitrary File Copy

A fully reproducible lab and a hand-written exploit for CVE-2015-3306 — built as a learning exercise in vulnerability research: patch diffing, manual triggering, and raw-socket exploit development.

The bug

ProFTPD's mod_copy module implements the SITE CPFR / SITE CPTO command pair, which copies files on the server side without transferring data to the client.

In version 1.3.5, neither handler checked whether the session was authenticated. The module simply assumed "nobody will send SITE commands before logging in" — a broken assumption that became a CVE. Any unauthenticated client could copy any file readable by the server process to any location writable by it.

The patch

The fix (commit 212d54271f, released in 1.3.5a) does two things:

  1. Adds an authentication gate at the top of copy_cpfr and :
copy_cpto
root@kitploit:~
authenticated = get_param_ptr(cmd->server->conf, "authenticated", FALSE);
if (authenticated == NULL || *authenticated == FALSE) {
  pr_response_add_err(R_530, _("Please login with USER and PASS"));
  errno = EPERM;
  return PR_ERROR(cmd);
}
  • Adds a CopyEngine on|off directive — previously the module could not even be disabled in builds that shipped it.
  • The full unified diff is in patch.diff. Reading patches is the skill: the fix tells you where the wound was.

    The lab

    The Dockerfile compiles ProFTPD 1.3.5 (the last vulnerable release) from the official source tarball with mod_copy enabled:

    root@kitploit:~
    docker build -t proftpd-135 .
    docker run -d --name lab135 -p 127.0.0.1:2121:21 -p 127.0.0.1:30000-30010:30000-30010 proftpd-135
    docker exec lab135 chmod 777 /home/ftp
    

    PassivePorts in proftpd.conf pins the data channel — FTP's two-channel architecture (control + dynamic data) is the reason naive container mappings fail: the control port works, the data port doesn't.

    The exploit

    exploit.py uses raw sockets — no ftplib, because libraries hide the protocol, and hiding the protocol is exactly what we are fighting:

    root@kitploit:~
    SITE CPFR /etc/segredo.txt   -> 350  (no USER/PASS sent: this IS the bug)
    SITE CPTO /home/ftp/...      -> 250  (arbitrary copy performed)
    USER ftp / PASS ...          -> 230  (login is only the exfil path)
    PASV / RETR                  -> 150 -> 226  (flag captured)
    DELE                         -> 250  (cleanup: no IOC left behind)
    

    Lessons learned (the actual point of this repo)

    • Banner != truth. Debian backports fixes without bumping versions; honeypots (Dionaea et al.) deliberately mimic vulnerable banners.
    • Exploitable bug != automatic exploit. The environment (filesystem permissions, AllowOverwrite, port mappings) decides the final impact.
    • Idempotency matters. A good exploit runs twice in a row — unique destination names (time.time_ns(), not time.time()), and no reliance on leftover state.
    • FTP replies have a state machine. 1xx is preliminary (expect more), 2xx complete, 3xx intermediate, 5xx error. RETR answers twice: 150, then 226. Drain both before the next command.
    • The target's logs are ground truth. When the client says "550" and you don't know why, the server's debug log (-d10) tells you exactly which check fired.
    • Cleanup is OPSEC. An exploit that leaves files behind is an exploit that leaves evidence behind.

    References

    • Fix commit: https://github.com/proftpd/proftpd/commit/212d54271f
    • CVE: https://nvd.nist.gov/vuln/detail/CVE-2015-3306

    Disclaimer

    For education and authorized lab use only. Running this against systems you do not own or have written permission to test is illegal.

    Download Tool