Jouons avec FTP
Suite à une discussion sur IRC, je me suis remis à m’amuser avec le protocole FTP.
J’en profite pour faire un topo rapide.
C’est quoi FTP
Comme son nom l’indique, FTP (File Transfer protocol) est un protocole de transport de fichiers. Il fonctionne en TCP contrairement à d’autres protocoles comme le TFTP qui fonctionnent en UDP.
Mais FTP, outre d’être difficile à administrer (pour le firewall notamment), est peu sécurisé. Nous verrons par la suite les limites de ce protocole. Il est a noter que la plupart des serveurs FTP actuels (et heureusement) permettent de limiter les problèmes.
Comment fonctionne FTP
FTP fonctionne sur deux canaux. Un canal pour les commandes et l’autre canal pour les données.
Nous supposons que nous avons :
Sur le client, nous allons nous connecter sur le serveur ftp avec telnet :
victime$ telnet 192.168.0.1 21
Trying 192.168.0.1...
Connected to 192.168.0.1.
Escape character is '^]'.
220 ProFTPD 1.2.8 Server (ProFTPD Default Installation) [gnunux.gnunux.info]
Commençons pour nous identifier :
USER gnunux
331 Password required for gnunux.
Comme indiqué, il faut mettre son mot de passe :
PASS motdepasse
230 User gnunux logged in.
Nous voilà connecté sur le serveur ! Nous pouvons maintenant découvrir les commandes de base en faisant "HELP". Par exemple "PWD" nous donne le répertoire courant, "SYST" nous donne le type de système.
Maintenant passons aux choses sérieuses. Pour l’instant nous sommes restés dans le canal commande.
FTP fonctionne en mode passif ou en mode actif. Dans le premier cas, le serveur ouvre un port non privilégié (supérieur à 1023) en attendant que le client se connecte sur le canal de donnée. Dans le deuxième cas, le client ouvre un port en attendant que le serveur se connecte depuis le port 20. Etudions dans la pratique ce que cela donne.
mode passif
En mode passif, faisons :
PASV
227 Entering Passive Mode (192,168,0,1,6,130).
Ici nous avons l’ip du serveur (192.168.0.1) et le port 6,130 (c’est bien des "," et non des "."). Pour calculer le port, il faut faire : 6x256+130 (donc 1666).
Depuis une autre console :
victime$ telnet 192.168.0.1 1666
Trying 192.168.0.1...
Connected to 192.168.0.1.
Escape character is '^]'.
Le telnet est en attente. Il faut demander au serveur de transmettre des données depuis le canal de commande :
LIST
150 Opening ASCII mode data connection for file list
226 Transfer complete.
Dans la fenêtre du canal de donnée nous avons la liste des fichiers des répertoires courant qui s’affiche :
drwx------ 2 gnunux users 4096 Nov 13 20:02 Amis
-rw------- 1 gnunux users 37035 Nov 24 11:28 Autre
drwx------ 4 gnunux users 4096 Nov 13 19:35 Contact
drwx------ 4 gnunux users 4096 Jan 1 23:05 Lettre
drwx------ 4 gnunux users 4096 Jan 1 23:05 Liste
drwx------ 2 gnunux users 4096 Jan 1 23:05 Travail
Connection closed by foreign host.
mode actif
Choisissons un port supérieur à 1023 au hazard ... disons 1867
Sur le client écoutons sur ce port avec netcat :
victime$ nc -l -p 1867
Enfin calculons les valeurs utilisées pour définir le port :
victime$ echo "1867/256" |bc
7
victime$ echo "1867%256" |bc
75
Le port 1867 est donc 7,75.
Passons donc en mode actif :
PORT 192,168,0,2,7,75
200 PORT command successful
LIST
150 Opening ASCII mode data connection for file list
Vous pouvez voir que la liste des répertoires est affichée dans la console contenant netcat.
Usurpation du canal de donnée
Il est facile de constater qu’aucun mécanisme ne permet de s’identifier sur le canal des données. Le serveur se contente de répondre à la première personne qui s’y connecte.
Il est facile de récuperer des données d’une session d’une autre personne.
Pour la suite, nous allons utiliser un petit script que j’ai écrit :

- ftp_passif.py.gz
- Script python de ma composition à décompresser (gunzip ftp_passif.py.gz) et à rendre exécutable (chmod +x ftp_passif.py).
victime$ ./ftp_passif.py
Dans une autre console, tape :
telnet 192.168.0.1 1818
Comme indiqué dans une autre console, il suffit de taper "telnet 192.168.0.1 1818" pour voir le contenu du répertoire.
Refaire l’expérience mais en faisant le telnet sur le deuxième client :
attaquant$ telnet 192.168.0.1 1818
Trying 192.168.0.1...
Connected to 192.168.0.1.
Escape character is '^]'.
drwx------ 2 gnunux users 4096 Nov 13 20:02 Amis
-rw------- 1 gnunux users 37035 Nov 24 11:28 Autre
drwx------ 4 gnunux users 4096 Nov 13 19:35 Contact
drwx------ 4 gnunux users 4096 Jan 1 23:05 Lettre
drwx------ 4 gnunux users 4096 Jan 1 23:05 Liste
drwx------ 2 gnunux users 4096 Jan 1 23:05 Travail
Le rebond FTP (ou bounce FTP)
Le rebond FTP est une technique de test de port d’une machine tiers en utilisant le protocole FTP.
Le principe est d’ouvrir, en mode actif, une connexion sur un port spécifique d’un autre machine (avec la commande PORT). Si le port est ouvert, le serveur FTP considérera que les données ont été transmis. Sinon une erreur sera retournée.
Pour la suite, nous allons utiliser un petit script que j’ai écrit :

- ftp_actif.py.gz
- Script python de ma composition à décompresser (gunzip ftp_actif.py.gz) et à rendre exécutable (chmod +x ftp_actif.py).
Sur le premier client faire :
victime$ nc -l -p 1982
et dans une autre console :
victime$ ./ftp_actif.py 192.168.0.2 1982
port ouvert
Sur un port fermé nous aurons :
victime$ ./ftp_actif.py 192.168.0.2 1983
port ferme
Attention, il est très rare que les serveurs FTP acceptent des ports privilégiés (inférieur a 1024) comme port de destination.
Maintenant si nous modifions l’ip, il est possible de s’assurer qu’un port est ouvert ou non.
Sur le premier client, faire :
victime$ nc -l -p 1672
et sur le deuxième client :
./ftp_actif.py 192.168.0.3 1672
port ouvert.
Se protéger
Avec proftpd, il suffit de mettre l’option "AllowForeignAddress" à "off".
| Fichier attaché | Taille |
|---|---|
| ftp_actif.py.gz | 659 octets |
| ftp_passif.py.gz | 709 octets |

Commentaires
> Jouons avec FTP
J’ai résolu le problème avec gzip ;)
> Jouons avec FTP
Il serait bien si on pouvait mettre en attachement de fichier python :/