0x01 MS08-067漏洞原理MS08-067漏洞是通过MSRPC over SMB通道调用Server服务程序中的NetPathCanonicalize函数时触发的,而NetPathCanonicalize函数在远程访问其他主机时,会调用NetpwPathCanonicalize函数,对远程访问的路径进行规范化,而在NetpwPathCanonicalize函数中存在的逻辑错误,造成栈缓冲区可被溢出,而获得远程代码执行(Remote Code Execution)。
所谓路径规范化,就是将路径字符串中的【/】转换为【\】,同时去除相对路径【.\】和【..\】。如:
**/*/./** => **\*\**
**\*\..\** => **\**
在路径规范化的操作中,服务程序对路径字符串的地址空间检查存在逻辑漏洞。攻击者通过精心设计输入路径,可以在函数去除【..\】字符串时,把路径字符串中内容复制到路径串之前的地址空间中(低地址),达到覆盖函数返回地址,执行任意代码的目的。
路径处理流程
NetpwPathCanonicalize函数并没有直接进行输入路径和规范化,而是继续调用了下级函数CanonicalizePathName来进行路径整理,将待整理的路径字符串进行规范化,然后再保存到预先分配的输出路径缓冲区buffer中。
路径处理流程:
1.检查待整理路径的第一个字符;
2.调用msvcrt.dll模块的wcslen函数计算路径长度;
3.调用msvcrt.dll模块的wcscat函数把待整理路径全部复制到新申请的内存中。
4.调用wcscpy函数,去掉待整理路径中第一个表示父目录的相对路径复制到strTemp,如:
\******\..\..\*** => \..\***
5.循环调用wcscpy,直到路径整理完毕。
在这里我们知道了,在规范化复制时要寻找表示父目录的【..\】字符串及其前面的一个【\】字符串,将这一段去掉并将新路径复制。
如图,第一次检查时去掉了第一个相对路径并复制到缓冲区
但是,当【..\】字符串在路径字符串的最前面时,那么其前面的一个【\】就在缓冲区外面了,就是在这里产生了向前(低地址)的溢出。
缓冲区溢出
需要明确的是,微软对路径规范化时的字符串复制可能出现的缓冲区溢出做了初步的防御。
在每次向缓冲区中复制字符串时,无论是用wcsccpy还是wcscat,在复制前总要比较源字符串的长度,保证长度小于某个值(207),否则不会继续复制,这一策略确保缓冲区不会向高地址溢出,即当前函数返回时不会发生问题。
但是注意,在规范化表示路径,寻找父目录的【..\】字符串前面的【\】字符时,程序做了判断和边界检查:如果当前比较字符的地址与源字符串地址相同,就表明整个字符串已经查找完毕,程序就会停止查找。
然而它唯独漏了一种情况,就是当父目录相对路径【..\】字符串在源字符串的开头时,在开始查找时比较的字符串(【\】到【..\】)位于缓冲区之外,这导致了复制的字符串向低地址的溢出,造成函数wcscpy的返回地址被覆盖。
0x02 漏洞还原分析
实验环境
靶机:Windows2003 SP0 EN
漏洞组件:netapi32.dll
工具:IDA Pro、OllyDbg
选择Windows XP SP3 EN系统主机作为分析环境,定位到包含该安全漏洞的系统模块netapi32.dll(路径C:\Windows\system32)和调用漏洞服务Server的进程svchost.exe,目标进程命令行为: