Serv-U漏洞以及原因分析(轉)

RegisterForBlog發表於2007-09-19
Serv-U漏洞以及原因分析(轉)[@more@]

  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 FF75F0 push [ebp-10]

  ;RtlGetFullPathName_U用來得到路徑的UNICODE字串,這個函式是由長度限制的,

  ;當長度大於0x208的時候無法正確得到路徑,即無法正確複製串到ebp-0C中。

  * Reference To: NTDLL.RtlGetFullPathName_U, Ord:01E7h

  |

  :77E80E1E FF15AC10E677 Call dword ptr [77E610AC]

  :77E80E24 3BC7 cmp eax, edi ;這個判斷不對,應該跳到錯誤處理去!

  ;但是由於前面的限制是0x20A,所以當用0x20A長的字串時就會判斷出錯,

  ;不會進入錯誤處理去,而是繼續對沒有得到內容的堆記憶體進行後面的操作,

  ;這就是出錯的根源

  :77E80E26 894508 mov dword ptr [ebp+08], eax

  :77E80E29 0F87CC9B0000 ja 77E8A9FB

  * Reference To: NTDLL.RtlUnicodeToMultiByteSize, Ord:0294h

  |

  :77E80E2F 8B356010E677 mov esi, dword ptr [77E61060]

  :77E80E35 50 push eax

  :77E80E36 FF75F4 push [ebp-0C]

  :77E80E39 8D4508 lea eax, dword ptr [ebp+08]

  :77E80E3C 50 push eax

  :77E80E3D FFD6 call esi ;call RtlUnicodeToMultiByteSize

  :77E80E3F 3BC3 cmp eax, ebx

  :77E80E41 0F8CAE9B0000 jl 77E8A9F5

  :77E80E47 395D08 cmp dword ptr [ebp+08], ebx

  :77E80E4A 0F8491000000 je 77E80EE1

  :77E80E50 395D14 cmp dword ptr [ebp+14], ebx

  :77E80E53 7420 je 77E80E75

  :77E80E55 8B45FC mov eax, dword ptr [ebp-04]

  :77E80E58 3BC3 cmp eax, ebx

  :77E80E5A 7419 je 77E80E75

  :77E80E5C 2B45F4 sub eax, dword ptr [ebp-0C]

  :77E80E5F D1F8 sar eax, 1

  :77E80E61 D1E0 shl eax, 1

  :77E80E63 50 push eax

  :77E80E64 8D45F8 lea eax, dword ptr [ebp-08]

  :77E80E67 FF75F4 push [ebp-0C]

  :77E80E6A 50 push eax

  :77E80E6B FFD6 call esi ;call RtlUnicodeToMultiByteSize----出錯!!!

  ;第2次呼叫RtlUnicodeToMultiByteSize的時候會把上面的錯誤顯現出來

  :77E80E6D 3BC3 cmp eax, ebx

  :77E80E6F 0F8C809B0000 jl 77E8A9F5

  ;-------------------------------------------------------------------------------------------

  最後一個call esi呼叫這裡

  Exported fn(): RtlUnicodeToMultiByteSize - Ord:0296h

  :77F83EA4 8B44240C mov eax, dword ptr [esp+0C]

  :77F83EA8 56 push esi

  :77F83EA9 33F6 xor esi, esi

  :77F83EAB D1E8 shr eax, 1

  :77F83EAD 803D14F3FC7700 cmp byte ptr [77FCF314], 00

  :77F83EB4 0F8598D30100 jne 77FA1252 ;會轉到77FA1252去執行

  :77F83EBA 8B4C2408 mov ecx, dword ptr [esp+08]

  :77F83EBE 8901 mov dword ptr [ecx], eax

  :77F83EC0 33C0 xor eax, eax

  :77F83EC2 5E pop esi

  :77F83EC3 C20C00 ret 000C

  ;-------------------------------------------------------------------------------------------

  跳到這裡

  * Referenced by a (U)nconditional or (C)onditional Jump at Address:

  |:77F83EB4(C)

  |

  :77FA1252 8BC8 mov ecx, eax

  :77FA1254 48 dec eax

  :77FA1255 85C9 test ecx, ecx

  :77FA1257 7424 je 77FA127D

  :77FA1259 8B4C240C mov ecx, dword ptr [esp+0C]

  :77FA125D 57 push edi

  :77FA125E 8D7801 lea edi, dword ptr [eax+01]

  * Referenced by a (U)nconditional or (C)onditional Jump at Address:

  |:77FA127A(C)

  |

  :77FA1261 0FB701 movzx eax, word ptr [ecx]

  ;這裡會有個迴圈不斷的取ecx的值,也就是前邊RtlAllocateHeap分配的那個堆,

  ;因為前面那個堆裡沒有正確存放內容,所以會造成不跳出迴圈,從而一直取到

  ;記憶體頁面不存在的地方

  

·上一篇:

·下一篇:
 
     最新更新
·

·

·

·

·

·

·

·

·

·

·

·

·

·

·

·

·

·

·

·

·

·

·

·

·

·

·

·

·

·


| | | | | | |

Copyright © 2004 - 2007 All Rights Reserved

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/10763080/viewspace-970282/,如需轉載,請註明出處,否則將追究法律責任。

Serv-U漏洞以及原因分析(轉)
請登入後發表評論 登入
全部評論

相關文章