
vsftpd 3.0.5 - High - Remote - Privilege leftover - cmds_denied misses RFC aliases (XRMD)
abraxaslabs.tech · github.com/abraxas · @abraxas_null · [email protected] · vsftpd-cmds-denied-alias
Class: Privilege leftover Reach: Remote
vsftpd 3.0.5 - Chris Evans
I pinned the official tarball, not a GitHub mirror and not a distro fork. SHA-256 26b602ae454b0ba6d99ef44a09b6b9e0dfa7f67228106736df1f278c70bc91d3. vsftpver.h VSF_VERSION "3.0.5".
cmds_denied is an exact uppercased token match in process_post_login (postlogin.c:140-184). Dispatch then ORs RFC 775 aliases onto the same handlers: RMD||XRMD (:263-264), also CWD||XCWD, MKD||XMKD, PASV||P@SW, plus separate EPSV / STOU / APPE. An operator who denylists RMD (the common DELE,RMD recipe) still lets XRMD rmdir.
This leftover is authenticated FTP integrity under a denylist the operator thought was closed. It is not unauth, not root, not a chroot escape, and not RCE.
| ID | no CVE yet |
| Class | Privilege leftover (cmds_denied exact token) |
| Reach | Remote (authenticated FTP) |
| CWE | CWE-863 |
| CVSS | High: 7.1 CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:H/A:N |
| Product | vsftpd (Chris Evans) |
| Affected | vsftpd 3.0.5 official tarball |
| Auth | FTP USER/PASS (lab: anonymous ftp) |
| License | GNU Affero GPL v3.0 |
| Lab | 127.0.0.1:18720 only |
Who: an authenticated FTP user (anonymous or local) on a daemon where the operator set cmds_denied. Default is unset. Virtual-user recipes the man page names share a guest uid, so Unix DAC cannot separate them. The session is already the mapped uid inside the usual chroot. cmds_denied was the extra control that was supposed to take the verb away.
| Method + sink | Privilege |
|---|---|
XRMD labdir after cmds_denied=RMD | handle_rmd -> str_rmdir of a directory the session uid can Unix-rmdir. Lab: RMD labdir 550, XRMD labdir 250, CWD labdir 550 (dir gone). Second MKD labctrl still 550 on RMD. |
| Method + sink | Privilege |
|---|---|
XMKD dir after cmds_denied=MKD | handle_mkd -> mkdir as the session uid |
XCWD path after cmds_denied=CWD | handle_cwd -> chdir. Then RETR if download_enable |
STOU / APPE after cmds_denied=STOR | handle_upload_common create / append. Needs write_enable |
EPSV / P@SW after cmds_denied=PASV | handle_pasv opens a data listener the denylist was meant to stop |
Lab proved only XRMD after RMD. The other aliases share the same str_equal gate and the same OR in dispatch. I did not exercise them.
None as a first-class leftover. cmds_denied is not a hide. XRMD does not list names.
Not in bar. Removing a directory is an integrity hit. A later CWD / RETR of that name 550s as a side effect.
cmds_denied (pre-login ignores it; USER/PASS/QUIT stay the pre-login table)allow_writeable_chroot default off; lab writes only under /incoming so the deny still holds)cmds_allowed fail-closed: unlisted verbs including XRMD stay 550write_enable=NO still blocks the write family (STOR/MKD/RMD/DELE/RNFR/RNTO/SITE/APPE/STOU)SITE vs site case bypass (ftpcmdio.c str_upper)cmds_denied=CHMOD never matches; kill chmod with chmod_enable=NO or cmds_denied=SITEI hunted hide/deny/cmds_denied on official 3.0.5. The gate is one walk of comma tokens and str_equal against the uppercased verb. There is no second check inside handle_rmd. RFC 775 still ships XRMD as RMD. Common advice is cmds_denied=DELE,RMD. That string never names XRMD.
Wrong turn: treating SITE vs site as a bypass. Verbs are uppercased. Treating cmds_allowed the same way: that list is fail-closed, so aliases that are not listed stay denied.
cd lab
./run.sh
Loopback 127.0.0.1:18720. Compose project vsftpd-cmds-denied-alias. Official 3.0.5 tarball in lab/ (SHA-256 above). cmds_denied=RMD, write_enable=YES, anonymous, writes only under /incoming. Witness VSFTPD-CMDS-DENIED-ALIAS-WITNESS. Last line:
SUCCESS vsftpd-cmds-denied-alias rmd=550 xrmd=250 dir-gone=yes VSFTPD-CMDS-DENIED-ALIAS-WITNESS
Deny the RFC aliases when denying the modern verb, or match aliases in cmds_denied (XCWD / XMKD / XRMD / XPWD / XCUP / P@SW / EPSV / STOU / APPE). Prefer cmds_allowed (allowlist).
Vendor intake is [email protected] (vsftpd). Unpaid. Do not open a public GitHub issue on any vsftpd mirror.
Abraxas Labs - abraxaslabs.tech - github.com/abraxas - @abraxas_null - [email protected]