• 2004-04-14

    Serv-U远程拒绝服务漏洞以及原因分析 - [网络技术(bbs.iohy.com交流)]

    版权声明:转载时请以超链接形式标明文章原始出处和作者信息及本声明
    http://qq4508509.yourblog.org/logs/147516.html

    Serv-U FTP Server远程拒绝服务漏洞以及原因分析 涉及程序版本: Serv-U FTP Server v4.0.0.4(以前版本也可能存在该漏洞,没有测试过) 漏洞类型: 远程拒绝服务 漏洞描述: 前几天使用了一下RhinoSoft出品的Serv-U FTP,感觉还不错,简单测试了一下其安全性,发现当用匿名用户登陆后,发送LIST NNNN...命令,后跟的字符数量达到253字节时,服务端报错,并且错误对话框无法关闭,只能重启Serv-U FTP服务才行。 由于是由长字符串造成的,我一开始还认为是溢出之类的漏洞。后来经过深入分析程序汇编代码,发现这不是一般的溢出,甚至可以说不是Serv-U的本身程序的问题,而是一个WIN32 API的设计上的BUG。 GetFullPathNameA这个API用来获取指定文件的路径,但是它在处理长文件名时没有考虑好边界条件,造成可能访问到不存在的内存地址,在Serv-U的例子里就造成了拒绝服务攻击。本来一般像这种访问不存在内存的漏洞,程序的异常处理都可以恢复过来的,不至于造成程序崩溃,但是正是由于这个问题是由系统DLL出错而造成的,而不是应用程序本身的问题,所以应用程序的异常处理例程无法正确处理该问题,从而导致了服务端程序崩掉。 不仅仅是LIST命令受该漏洞影响,所有后跟参数是文件名的命令都有这个问题,例如MDTM等等。另外触发这个漏洞的串长度是根据ftp根目录的设置不同而定的,我写了个程序来测试该漏洞,程序见后面。由于这个漏洞无法用来得到权限,所以也懒得报告到BUGTRAQ上去了,不过分析漏洞的过程还是让我有点收获,起码知道了编程中哪些地方是程序员容易忽视而造成安全漏洞的地方,微软的程序员也一样犯这样的错误。 程序分析: 下面是通过对该程序的反汇编代码的分析来解释造成该漏洞的原因。 由于反汇编出的代码有几十M之大,分析的时候难免出错,敬请各位发现问题的同志指出。 Serv-U在接受到LIST NNN...命令后对文件名进行处理,会进入下面 这一段程序: * Referenced by a CALL at Addresses: |:005A4A8F , :005A4C97 | :005A338C 55 push ebp :005A338D 8BEC mov ebp, esp :005A338F 83C4F8 add esp, FFFFFFF8 :005A3392 53 push ebx :005A3393 56 push esi :005A3394 57 push edi :005A3395 8B7D08 mov edi, dword ptr [ebp+08] :005A3398 6804010000 push 00000104 :005A339D E802F9FEFF call 00592CA4 :005A33A2 59 pop ecx :005A33A3 8BD8 mov ebx, eax :005A33A5 85C0 test eax, eax :005A33A7 7507 jne 005A33B0 :005A33A9 33C0 xor eax, eax :005A33AB E9A9000000 jmp 005A3459 * Referenced by a (U)nconditional or (C)onditional Jump at Address: |:005A33A7(C) | :005A33B0 8D55FC lea edx, dword ptr [ebp-04] :005A33B3 52 push edx :005A33B4 53 push ebx :005A33B5 6804010000 push 00000104 :005A33BA 8B4D0C mov ecx, dword ptr [ebp+0C] :005A33BD 51 push ecx ;这里是ftp跟目录加上LIST参数 * Reference To: KERNEL32.GetFullPathNameA, Ord:0000h | :005A33BE E89F630100 Call 005B9762 ;调用GetFullPathNameA ;------------------------------------------------------------------------------------------- ;调用到Kernel32.dll里的GetFullPathNameA函数 Exported fn(): GetFullPathNameA - Ord:012Ah :77E80DBD 55 push ebp :77E80DBE 8BEC mov ebp, esp :77E80DC0 83EC24 sub esp, 00000024 :77E80DC3 53 push ebx :77E80DC4 56 push esi :77E80DC5 8B7514 mov esi, dword ptr [ebp+14] :77E80DC8 33DB xor ebx, ebx :77E80DCA F7DE neg esi :77E80DCC 57 push edi :77E80DCD 8D45FC lea eax, dword ptr [ebp-04] :77E80DD0 FF7508 push [ebp+08] :77E80DD3 895DF8 mov dword ptr [ebp-08], ebx :77E80DD6 1BF6 sbb esi, esi :77E80DD8 23F0 and esi, eax :77E80DDA 8D45EC lea eax, dword ptr [ebp-14] :77E80DDD 50 push eax :77E80DDE E81E89FEFF call 77E69701 :77E80DE3 85C0 test eax, eax :77E80DE5 0F84039C0000 je 77E8A9EE :77E80DEB 64A118000000 mov eax, dword ptr fs:[00000018] :77E80DF1 8B4030 mov eax, dword ptr [eax+30] :77E80DF4 BF0A020000 mov edi, 0000020A ;长度限制,不正确!!! ;这里0x20A是分配的堆的大小,同时也作为后边判断RtlGetFullPathName_U ;返回长度的比较长度的限制 :77E80DF9 57 push edi :77E80DFA FF35B0F7EB77 push dword ptr [77EBF7B0] :77E80E00 FF7018 push [eax+18] ;分配0x20A字节的内存堆 * Reference To: NTDLL.RtlAllocateHeap, Ord:014Ah | :77E80E03 FF150410E677 Call dword ptr [77E61004] :77E80E09 3BC3 cmp eax, ebx :77E80E0B 8945F4 mov dword ptr [ebp-0C], eax :77E80E0E 0F84C69B0000 je 77E8A9DA :77E80E14 56 push esi :77E80E15 50 push eax :77E80E16 6808020000 push 00000208 :77E80E1B

    收藏到:Del.icio.us




发表评论

您将收到博主的回复邮件
记住我