基本信息
该漏洞出现在 IIS 6.0 的WebDAV服务上,经过分析确定是在httpext.dll中进行处理,其中PoC以及相关的出错函数也已经给出,在ScStoragePathFromUrl中,大致看一下该函数,就是将传入的URL存储。最后的一个memcpy将最终导致覆盖到虚表指针 导致任意代码执行。
附加的是w3wp.exe @Keoyo_k0shl
参考:https://www.seebug.org/vuldb/ssvid-92834
环境:
Win server 2003 sp2
IIS 6.0 开启 WebDAV
断点进入(关键断点位置)
1
| 0 e 673f6c7b 0001 (0001) 0:**** httpext!ScStoragePathFromUrl
|
第一次命中
edx 作为参数传入 http
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| 0:018> g Breakpoint 0 hit eax=012cf800 ebx=01e4ed58 ecx=01e4d968 edx=01e4f460 esi=00000000 edi=77ba8ef2 eip=673f6c7b esp=012cf79c ebp=012cf7ac iopl=0 nv up ei pl nz na pe nc cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000206 httpext!ScStoragePathFromUrl: 673f6c7b b8150d4167 mov eax,offset httpext!swscanf+0x14b5 (67410d15) 0:008> dc edx 01e4f460 00740068 00700074 002f003a 006c002f h.t.t.p.:././.l. 01e4f470 0063006f 006c0061 006f0068 00740073 o.c.a.l.h.o.s.t. 01e4f480 0061002f 00610061 00610061 00610061 /.a.a.a.a.a.a.a. 01e4f490 78636f68 71337761 47726936 4b777a39 hocxaw3q6irG9zwK 01e4f4a0 75534f70 48687a4f 6d545663 39536845 pOSuOzhHcVTmEhS9 01e4f4b0 5567506c 33646763 78454630 54316952 lPgUcgd30FExRi1T 01e4f4c0 6a514c58 42317241 58507035 6c473664 XLQjAr1B5pPXd6Gl 01e4f4d0 546a3539 54435034 50617752 6d4b3232 95jT4PCTRwaP22Km
|
也正是 前面传入的URL作了一次MultiByteToWideChar
简单跟一次之后 一共命中了6次:
前三次一起 checkif….
第一次检查
第二次 数据 拷贝 (http://aaaaaaa) 主要目的是为了覆盖一个栈地址,该地址用于后面的堆分配 指定位置分配(目的是为了绕过gs的保护)
第三次 数据 拷贝 (http://bbbbbbb) 布局作为后面的执行代码
后三次一起 CParseLockTokenHeader
第四次开始 进入 httpext!CParseLockTokenHeader::HrGetLockIdForPath
第四次不进行复制
第五次 对第一个处理 用来布局 来覆盖到虚表指针 指向前面两次的数据拷贝 (因此此时虚函数指针地址在复制的首地址后面,导致复制成为可能)
第六次 对第二个处理 触发
触发 调用的是 ScStripAndCheckHttpPrefix -> ScStripAndCheckHttpPrefix(call dword ptr [eax+24h])开始ROP
最后一次命中的数据 可以看到正好就是 第二个URL中的数据,即为ROP + shellcode 然后调用执行
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
| 0:008> dc ecx 680313c0 680313c0 68006e4f 68006e4f 766a4247 ...hOn.hOn.hGBjv 680313d0 680313c0 4f744257 52345947 4b424b66 ...hWBtOGY4RfKBK 680313e0 786f7464 68016082 727a5135 4d47747a dtox.`.h5QzrztGM 680313f0 57574459 6800b113 6e6f3176 680124e3 YDWW...hv1on.$.h 68031400 68031460 7ffe0300 ffffffff 680313c0 `..h...........h 68031410 6803046e 7470716e 68031434 680129e7 n..hnqpt4..h.).h 68031420 68009391 666e3931 30524955 766b546b ...h19nfUIR0kTkv 68031430 7961724a 6803141c 68006e05 79687732 Jray...h.n.h2why 0:008> dc ecx+0x24 680313e4 68016082 727a5135 4d47747a 57574459 .`.h5QzrztGMYDWW 680313f4 6800b113 6e6f3176 680124e3 68031460 ...hv1on.$.h`..h 68031404 7ffe0300 ffffffff 680313c0 6803046e ...........hn..h 68031414 7470716e 68031434 680129e7 68009391 nqpt4..h.).h...h 68031424 666e3931 30524955 766b546b 7961724a 19nfUIR0kTkvJray 68031434 6803141c 68006e05 79687732 366c4d69 ...h.n.h2whyiMl6 68031444 4d704468 68008246 32534877 68021daa hDpMF..hwHS2...h 68031454 43356f6a 680313f8 680129e7 00560056 jo5C...h.).hV.V. 0:008> dc 68031464 00410059 00340034 00340034 00340034 Y.A.4.4.4.4.4.4. 68031474 00340034 00340034 00410051 00410054 4.4.4.4.Q.A.T.A. 68031484 00410058 0041005a 00410050 00510033 X.A.Z.A.P.A.3.Q. 68031494 00440041 005a0041 00420041 00520041 A.D.A.Z.A.B.A.R. 680314a4 004c0041 00590041 00490041 00510041 A.L.A.Y.A.I.A.Q. 680314b4 00490041 00510041 00500041 00350041 A.I.A.Q.A.P.A.5. 680314c4 00410041 00500041 005a0041 00410031 A.A.A.P.A.Z.1.A. 680314d4 00310049 00490041 00490041 004a0041 I.1.A.I.A.I.A.J. 0:008> dc 680314e4 00310031 00490041 00490041 00580041 1.1.A.I.A.I.A.X. 680314f4 00350041 00410038 00500041 005a0041 A.5.8.A.A.P.A.Z. 68031504 00420041 00420041 00490051 00410031 A.B.A.B.Q.I.1.A. 68031514 00510049 00410049 00510049 00310049 I.Q.I.A.I.Q.I.1. 68031524 00310031 00410031 00410049 0051004a 1.1.1.A.I.A.J.Q. 68031534 00310049 00590041 005a0041 00410042 I.1.A.Y.A.Z.B.A. 68031544 00410042 00410042 00410042 00330042 B.A.B.A.B.A.B.3. 68031554 00410030 00420050 00340039 004a0034 0.A.P.B.9.4.4.J.
|
然后继续往前查看 究竟是什么时候修改覆盖的
覆盖ROP+shellcode(第三次击中)
这部分其实是拷贝URL2中的内容,将其拷贝到前面设定的起始地址
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| 0:008> dc ebp-450 012cf348 680312c0 00000000 00000310 01fc0070 ...h........p... 012cf358 012cf40c 003a0063 0069005c 0065006e ..,.c.:.\.i.n.e. 012cf368 00700074 00620075 0077005c 00770077 t.p.u.b.\.w.w.w. 012cf378 006f0072 0074006f 0062005c 00620062 r.o.o.t.\.b.b.b. 012cf388 00620062 00620062 61757948 6f674f43 b.b.b.b.HyuaCOgo 012cf398 48456b6f 67753646 38714433 5a625765 okEHF6ug3Dq8eWbZ 012cf3a8 56615435 6a536952 384e5157 63555948 5TaVRiSjWQN8HYUc 012cf3b8 43644971 34686472 71794758 6b55336b qIdCrdh4XGyqk3Uk 0:008> dc 680312c0 680312c0 003a0063 0069005c 0065006e 00700074 c.:.\.i.n.e.t.p. 680312d0 00620075 0077005c 00770077 006f0072 u.b.\.w.w.w.r.o. 680312e0 0074006f 0062002f 00620062 00620062 o.t./.b.b.b.b.b. 680312f0 00620062 61757948 6f674f43 48456b6f b.b.HyuaCOgookEH 68031300 67753646 38714433 5a625765 56615435 F6ug3Dq8eWbZ5TaV 68031310 6a536952 384e5157 63555948 43644971 RiSjWQN8HYUcqIdC 68031320 34686472 71794758 6b55336b 504f6d48 rdh4XGyqk3UkHmOP 68031330 34717a46 74436f54 6f6f5956 34577341 Fzq4ToCtVYooAsW4
|
覆盖虚函数指针(第五次击中)
这个操作在ScStoragePathFromUrl时 memcpy处理
首先进入的是 httpext!CParseLockTokenHeader::HrGetLockIdForPath,这里是来调用该函数的,因此核心的两个参数,虚函数地址,以及复制的起始地址都是在这里。
1 2 3 4 5 6 7 8 9
| 673f575c 85c0 test eax,eax 673f575e 0f84ee000000 je httpext!CParseLockTokenHeader::HrGetLockIdForPath+0x22b (673f5852) 673f5764 8b0b mov ecx,dword ptr [ebx] ds:0023:012cfbe8=01e4ed58 673f5766 8d85d4fdffff lea eax,[ebp-22Ch] 673f576c 50 push eax 673f576d ff75ec push dword ptr [ebp-14h] 673f5770 ffb5e0feffff push dword ptr [ebp-120h] 673f5776 e8d63cffff call httpext!CMethUtil::ScStoragePathFromUrl (673e9451) 673f577b 8985c8fdffff mov dword ptr [ebp-238h],eax
|
虚函数地址:ecx = [012cfbe8] = 01e4ed58
复制的首地址:012cfab4
因此进行赋值的时候溢出必定会改变012cfbe8的值,因此将会导致下次执行时虚函数的地址发生改变,导致代码执行。
继续:httpext!CParseLockTokenHeader::HrGetLockIdForPath调用之前会首先访问的httpext!CMethUtil::ScStoragePathFromUrl,然后经过它进行调用。
此时虚函数的首地址发生了变化,01e4d968
复制的初始地址为 [012cf95c]=012cfab4
虚表部分地址为 [012cfab0+0x10] = 01e4d968
1 2 3 4 5 6 7 8 9 10 11 12
| httpext!CMethUtil::ScStoragePathFromUrl: 673e9451 8bff mov edi,edi 673e9453 55 push ebp 673e9454 8bec mov ebp,esp 673e9456 8b4910 mov ecx,dword ptr [ecx+10h] 673e9459 8b5508 mov edx,dword ptr [ebp+8] 673e945c 6a00 push 0 673e945e ff7510 push dword ptr [ebp+10h] 673e9461 ff750c push dword ptr [ebp+0Ch] ss:0023:012cf95c=012cfab4 673e9464 e812d80000 call httpext!ScStoragePathFromUrl (673f6c7b) 673e9469 5d pop ebp 673e946a c20c00 ret 0Ch
|
因此在最后一次执行过程中:成功覆盖到第三次拷贝的地址
即这里的ecx
mov ecx,dword ptr [ebx] ds:0023:012cfbe8=680313c0
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| 673f5708 e8a70d0000 call httpext!ScCanonicalizePrefixedURL (673f64b4) 673f570d 8bd8 mov ebx,eax 673f570f 85db test ebx,ebx 673f5711 0f8519010000 jne httpext!CParseLockTokenHeader::HrGetLockIdForPath+0x209 (673f5830) 673f5717 8b45e8 mov eax,dword ptr [ebp-18h] 673f571a 8b9dc4fdffff mov ebx,dword ptr [ebp-23Ch] 673f5720 8b0b mov ecx,dword ptr [ebx] ds:0023:012cfbe8=680313c0 673f5722 c1e803 shr eax,3 673f5725 8985d4fdffff mov dword ptr [ebp-22Ch],eax 673f572b 8d85d4fdffff lea eax,[ebp-22Ch] 673f5731 50 push eax 673f5732 ff75ec push dword ptr [ebp-14h] 673f5735 ffb5e0feffff push dword ptr [ebp-120h] 673f573b e8113dffff call httpext!CMethUtil::ScStoragePathFromUrl (673e9451)
|
总结
属于栈溢出,在第二次进入关键函数的时候就应该存在溢出了,因此Fuzz应该只需要一个URL包即可,加两个应该只是为了后面的利用。
猜测的执行流程如下(次数代表击中关键函数ScStoragePathFromUrl):
第一次没太大用处,第二次 通过memcpy拷贝 aaa那里的数据 溢出覆盖第三次的堆地址首地址(由栈区的一个变量决定);因此第三次拷贝属于 指定地址拷贝;第四次也是检查;第五次溢出覆盖函数指针指向第三次设计好的地址(这里有个疑惑就是函数指针的地址会在正常堆分配地址之后,所以导致覆盖的出现),第六次调用触发执行