首页
社区
课程
招聘
[原创]漏洞考古:MS08-067详细分析
发表于: 2022-3-4 17:25 20105

[原创]漏洞考古:MS08-067详细分析

2022-3-4 17:25
20105

1. 漏洞简述

2. 组件概述

SMB是一种协议名,smb服务的作用在于计算机间共享文件、打印机和串口等。

Server Message Block Protocol,服务器信息块协议(SMB),为网络计算机客户程序提供一种从服务程序读写文件并请求服务的方法。SMB协议可在互联网的TCP/IP协议或者互联网数据包交换和NetBEUI等协议之上使用。使用SMB协议,应用程序可访问远程服务器的文件以及打印机、信槽和命名管道等资源。因而,客户程序可以读、写以及更新远程计算机上的文件,它也可以跟接收SMB客户请求的任意服务程序通信。

SMBv2是SMB协议的第二版本,相较SMBv1做了诸多扩展,部分数据包结构发生了变化,但仍保留了SMBv1的部分基本特征。

3. 漏洞利用

MS08-067漏洞是通过MSRPC over SMB通道调用Server服务程序中的NetPathCanonicalize函数时触发的。而NetpwPathCanonicalize函数在远程访问其他主机时,会调用CanonicalizePathName函数,对远程访问的路径进行规范化(将路径字符串中的'/'转换为'\',同时去除相对路径".\"和"..\"),而在CanonicalizePathName函数中调用的RemoveLegacyFolder发生了栈缓冲区溢出,可以造成RCE。

利用该漏洞可以达到远程代码执行的效果,通过使用不同的shellcode,可以实现任意功能,但是shellcode空间大小有限制。

4. 漏洞影响

根据Metasploit 中的Exp确定实际可以被攻击的操作系统版本。

Windows 2000、2003 SP0\SP1\SP2、XP SP0/SP1/SP2/SP3

操作系统版本:

软件版本:

漏洞产生于netapi32.dll,问题发生在其导出函数NetpwPathCanonicalize所调用的子函数CanonicalizePathName中的RemoveLegacyFolder函数中,原因为其在向上遍历\字符时栈首地址空间的边界检查无效,从而导致遍历完成,进行目录字符拷贝时,可以经过构造产生栈溢出,覆盖到返回地址中。

移除经典路径:

RemoveLegacyFolder函数的作用就是将路径中的经典路径去除。

1635422602301

函数实现思路:

移去经典路径.\

1635422546832

从路径开头向右遍历依次去除.\即可。

移去经典路径..\

1635423518681

对于经典目录..\

如果p1为当前的指针,p2和p1总是相差3个字符的位置,因为p2到p3中间的路径长度FOLDER2是不固定的,所以无法直接获取到p3的位置,对于获取到p3的位置,主要有以下两种思路。

RemoveLegacyFolder就是采用思路2来移除经典路径..\的,向前搜索的过程存在风险,并且对其边界检查无效,从而导致了缓冲区溢出的产生。

函数调用链 NetpwPathCanonicalize->CanonicalizePathName->RemoveLegacyFolder

函数作用:NetpwPathCanonicalize用于格式化网络路径字符串。

如果prefix串非空,将prefix串与path串用\相连,并复制输出到串can_path中,输出串的容量为maxbuf字节大小。

函数原型

用ida Pro加载netapi32.dll,定位到NetpwPathCanonicalize函数中,定位到调用CanonicalizePathName函数的位置。

1635472579870

函数执行流程:CanonicalizePathName函数中,对传入的prefix参数进行长度判断其不超过0x208,判断prefixSize + pathSize的长度不超过0x207,检查通过后拼接prefixpathwchPathBuffer路径缓冲区中,将路径缓冲区中的路径字符串中的/替换成\,检查Dos路径类型,将wchPathBuffer字符缓冲区传入RemoveLegacyFolder函数中用来移除经典路径。

在函数开始的位置检查pwchPrefix指向的地址是否为空。

1635909178281

判断pwchPrefix索引为0的字符的值不为0,字符串的长度长度不大于0x208,符合判断条件后,将pwchPrefix前缀字符串拷贝到wchStrBuffer缓冲区中,判断pwchCanPath缓冲区的pwchPrefixSize+1下标的位置是否为\/者,如果不是则在wchPathBuffer中拼接\\

1635910542380

判断参数pwszPath的开头部分是否是\或者/符号,如果是的话,对其指针+1。

1635910719853

获取pwchPath的长度,检查,pwchPrefixSize <=pwchPathSize + pwchPrefixSize <= 0x207是否比Path本身的长度小,是否大于0x207。

从这里可以看到,构造shellcode时,有长度限制,即不能超过0x207 * 2 => 1038个字节(这里使用的wcslen,unicode占用两个字节的数据,所以×2)

1635910756884

1635910874883

检查通过,将pwchPath拷贝到wchPathBuffer缓冲区中,接下来替换路径缓冲区中的/字符为\字符,检查DOS路径类型,将处理完后的缓冲区的地址,送入RemoveLegacyFolder中进行去除经典路径。

1635911323436

函数执行流程:RemoveLegacyFolder函数首先判断首字符是否是\然后向后遍历寻找\..\,寻找到后经过判断将经典路径中后一个\的位置后的路径字符串,拷贝到经典路径中第一个\的位置,然后向前遍历\定位到上级目录,接着向后遍历寻找\..\,接着进行第二次移除经典路径的操作。

跟进RemoveLegacyFolder函数中,函数开头判断传入的路径缓冲区索引为0的字符是否为\或者/

1635872312978

判断路径缓冲区索引为1的字符是否是\或者/

1635872471948

接着更新p1指针的值为字符缓冲区的首地址,向后遍历,判断p1指向的字符否为.

1635872835355

当p1指向的字符为\时,更新指针p3为p2的值,更新变量temp为p1的值,执行完成后跳回到循环中。

1635873376077

当p1指向的字符为.时,判断其是否为经典路径\..\,符合条件后,从p1+4的位置开始的路径(为经典路径后的位置),拷贝到p3指向的位置(p3指向字符\),此处操作的作用为移除经典路径\..\极其上级目录。

1635875274951

1635874358001

接着向下执行。

更新指针:更新temp变量为p3的值,更新指针p1为p3的值,更新eax为p3-2的值。

向前遍历\

边界检查:判断eax指向的地址是否等于字符缓冲区的起始地址。

在第一次执行到时,eax就已经超过了缓冲区的头部,向上越界越界了,此处再进行jz相等条件的比较是无效的,应该将其中的jz 跳转改为jbe 小于等于。

无效的边界检查和使用不安全的wcscpy函数,是导致溢出的直接原因。

在向前获取到\的地址后,p3指针指向该地址。

1635875442254

向下执行,跳转到向后遍历寻找p1指向的.的部分,紧接着判断经典路径,进行拷贝操作。

当p1指向.时跳出循环,判断路径是否是/../,判断p3指向的地址是否为空地址,判断无误后开始进行拷贝,由于此时p3指向的地址,已经远远超过缓冲区的地址,所以此时使用wcscpy函数进行拷贝会产生溢出,经过精心构造,覆盖返回地址,从而控制eip。

分析到这里可以发现,第二次移除经典路径,向上遍历到的\的位置至关重要。

接下来开始分析《0day安全》书里的poc和Metasploit的exp是如何产生\,如何构造攻击包从而覆盖返回地址,过掉系统保护,从而执行shellcode的。

本地溢出使用的poc为《0day安全》26.4.5章节中的ms08-067_failwest.c的基础上进行修改。

修改了偏移量和jmp esp的地址。

使用Visual Studio 2019 Debug版本编译后,偏移量发生了变化(112 => 109),我们用来调试的目标操作系统与书中也发生了变化,所以要进行更新。

编译选项:

属性页->Debug->配置属性->

关闭系统DEP

系统属性->高级->性能->设置->性能选项->数据执行保护。

源码:

编译后执行,可以看到成功执行了弹窗。

1635929511800

接下来使用ollydbg进行动态调试,定位到溢出点。

定位到main函数中调用NetpwPathCanonicalize函数调用的位置,分析参数可以看到攻击流量由path参数传入,prefix参数为空。

1635930784051

跟进NetpwPathCanonicalize中定位到CanonicalizePathName调用位置。

1635931314465

在CanonicalizePathName函数中,当传入的prefix参数为空时,不执行对prefix参数的长度判断,直接判断Path参数的长度是否符合要求 pwchPrefixSize <=pwchPathSize + pwchPrefixSize <= 0x207

1635932300984

1635932422840

判断完后拼接到路径缓冲区中。

1635932742303

然后进行替换/\,检查DOS路径,移除经典路径的操作。

1635932893311

跟进移除经典路径函数0x5FDDA220中,判断首字符为\进行跳转。

1635933096583

判断第二个字符是否是\或者/,不相等则进行跳转。

1635933557247

1635933379817

接着向后查找经典路径,判断是否为经典路径\..\,符合条件进行copy,此时第一次copy时src在范围内,不会产生溢出。

1635933746088

向后执行,向前遍历上一个\的位置,此处的越界检查是无效的是导致溢出的直接原因

1635945714067

这里直接F4跳出循环,此时eax指向了0x12F332,也就是\netapi32.dll字符串,该字符串由Loadlibrary函数执行后产生(使用Visual Studio 2019 Debug编译的程序,在windows xp sp3系统中执行)。

1635933894776

向上遍历到后,更新到p3指针中,继续跳转到向后遍历寻找字符.,判断是否是经典路径/../

1635946421381

判断完成后,进行copy,可以看到此时p3指向的目标地址0x12332,已经超出了当前的栈顶0x12F3FC,所以在copy以后会覆盖栈顶及返回地址,测量与返回地址的偏移,去构造就可以控制eip。

1635949212584

进入函数wcscpy中,可以测算拷贝的目标地址与返回地址之间的偏移为0x12F3F8 - 0x12F332 = 0xC6 = 198,因为是unicode字符串,所以要把填充的字符数量根据偏移除以2,为99,所以最终需要填充的字符数量为99个。

1635949538621

继续执行,在本地测试中关掉了系统DEP保护,所以这里直接用了jmp esp跳板的地址来跳转到栈上执行shellcode。

1635950541678

poc使用的攻击数据布局如下。

1635952214068

在数据窗口定位到前面匹配到的\在内存中的位置0x12F332

1635951412876

执行过Loadlibrary后,其位置写入了/netapi32.dll字符串。

1635951276234

查看netsvcs服务(提供SMB服务的svchost进程)进程ID。

1635953630856

用OD附加该进程,在netapi32.dll中的NetpwPathCanonicalize上下断点,右键查看所有模块中的名称。

1635954224921

跟进函数在头部下断点,按F9键运行。

-1635954404915

在Metasploit中使用ms08-067漏洞进行攻击。

1635954725998

靶机在接收到远程RPC调用NetpwPathCanonicalize的攻击流量后,会在设置的断点处断下,接下来就可以进行动态调试了。

1635954973455

在此处建立虚拟机快照,方便后续调试!

对传入的参数进行分析,查看其与本地溢出有什么不同。

同样是在path参数中传递攻击数据,不过其设置了prefix\,设置can_path缓冲区的大小为674。

1635955896206

动态执行的流程和前面几乎是一样的,之前已经分析过了,在这里我们主要关注以下三点。

定位到第二次执行的位置wcscpy

1635988512781

在内存中窗口定位到\的位置,恢复快照(因为有ASLR,栈地址下次攻击流量再打过来就变了),对0x1B4F444\的位置下内存写入断点,在此处断下,此时并不能看到是哪条指令对其写入了\

1635989616178

再次恢复快照,按F4执行到0x7C933C90处,逐行执行,发现是在7C933C9F E8 F1D5FEFF call ntdll.RtlInitUnicodeString处写入了数据。

再次恢复快照跟进函数中,重复流程,最终在函数内定位到写入\的位置。

1635990009682

进行栈回溯分析,查看是什么原因导致了该处指令,向0x1B4F444写入0x5C字符。

0x5C字符产生的原因

经过分析,发现写入的0x5C是其传入的unicode字符串的长度 * 2 + 2的值。

1635991273134

接着向上进行栈回溯分析,查看调用点在哪里,用于计算长度产生\的字符串是属于Path参数中的,所以几乎可以断定,这里的\是通过构造攻击包而产生的,一定在NetpwPathCanonicalize的调用范围内。

第一层

1635995702679

第二层

1635995741870

第三层,可以看到来到了CanonicalizePathName函数中的位置,产生\的原因在CheckDosPathType这个API之中。

1635995813071

搞清楚了调用关系,现在可以用ida来正向分析流程,来判断攻击包里是什么触发导致了其写入\的原因了。

跟进CheckDosPathType函数中,跟踪参数eax的值。

跟进ntdll.RtlIsDosDeviceName_U@4函数中,发现函数内部也没有进行其他处理,跟进该函数内调用的_RtlIsDosDeviceName_Ustr函数中。

1635996726628

RtlIsDosDeviceName_Ustr函数中,

发现其从后向前遍历路径字符串,寻找倒数第一个\/: 字符。

1635997755472

然后判断其后面的第一个字符是否是lcpa的任意一个(这里会将大写转换为小写),符合条件才会调用RtlInitUnicodeString函数,其unicode字符串的长度 * 2 符合0x5E才能写入\

1635998094944

因为函数的栈是向上生长的,写入\处的调用链为CanonicalizePathName->CheckDosPathType->ntdll.RtlIsDosDeviceName_U@4->ntdll._RtlIsDosDeviceName_Ustr->RtlIsDosDeviceName_Ustr->ntdll.RtlInitUnicodeString

而溢出函数wscpy的调用链为CanonicalizePathName->RemoveLegacyFolder->wcscpy,所以wcscpy的返回地址在栈中的位置,必定在写入\位置的下面,所以就会导致了可以测算偏移,来构造填充可以精确的覆盖到返回地址。

这里主要分析溢出后执行的路径,观察其是如何关掉DEP保护的。

在wscpy执行后,覆盖到返回地址的值为0x58FC17C2,执行跟进,发现其是利用NtSetInformationProcess来关闭DEP保护的,而eax指向的地址存储着20408的值,该地址在所有版本的操作系统中都是一段可读写的空间。NtSetInformationProcess执行时需要传入这类的空间。

1635999839129

执行到返回后,跳转到0x58F807这里是内平栈,所以其后紧跟的4个字节为填充,跳转到了call esi的位置。

1636000060436

esi即p1指针一直为\后的位置,跳转过去后发现这里填充了一个jmp 指令,跳转到了shellcode,到这里执行流程完成。

1636000180132

根据上述的调试过程来分析其攻击数据的内存布局。

1636000619385

https://github.com/jionyeahgithub/Arbang/tree/master/%E7%BB%8F%E5%85%B8%E9%87%8D%E7%8E%B0ms08-067%E6%BC%8F%E6%B4%9E%E8%AF%A6%E5%B0%BD%E5%88%86%E6%9E%90%E4%B8%8E%E5%88%A9%E7%94%A8%E8%BF%9B%E9%98%B6

MS08-067的漏洞触发的条件之一是RPC的参数Path中存在路径穿越 /../../;此特征较明显,因此防御人员很可能通过此特征进行拦截。

根据其在CanonicalizePathName函数中,会在调用RemoveLegacyFolder,自动将/替换为\的功能点,可以将其变换成如下形式,来绕过拦截。

参考系列文章:https://mp.weixin.qq.com/s/5jy2MWjDb3nuERNgDV_8Hw

还可以通过调整布局的方式,来获取更大的shellcode空间。

对于二进制漏洞的研究来说,不仅要知其原理,也要知道其使用场景,才能够更好的做武器化的开发。

在红队攻击中,对于二进制RCE漏洞,很少在公网暴漏的目标能够成功,一般会用来攻击内网主机,把对方内网的机器,通过流量代理,代理到公网的机器上。

1635778110935

在图中192.168.26.134是我们的攻击机。

IP为192.168.26.128是目标暴漏在公网上的Web服务器,其内网地址为172.20.1.112

内网IP为192.168.52.143的内网数据库服务器,是我们想要进行攻击的目标。

我们已经获取了Web服务器192.168.26.128的权限,继续向内网中渗透。

但是攻击者的PC无法直接访问内网的数据库服务器172.20.1.123,web服务器可以直接访问数据库服务器,数据库服务器为英文版本的Windows 2003Server SP2系统,其445端口的SMB服务存在MS08-067漏洞。

我们可以以Web服务器为跳板,将内网数据库服务器的445端口映射到Web服务器的1234端口,使用Metasploit对映射到的Web服务器1234端口发送MS08-067的攻击流量进行攻击。

其攻击流量会由Web服务器的1234端口,转发到内网数据库服务器的445端口中去。

攻击成功后,在Web服务器将内网数据库服务器反弹shell的流量转发到攻击机上。

这里我们使用lcx来进行流量转发,需要在我们已经拿下权限的Web服务器中上传lcx.exe

将内网数据库服务器的445端口映射到Web服务器上的1234端口,即监听端口1234,将所有发往192.168.26.128:1234的流量,转发到172.20.1.123:445

1635779741322

设置msf的payload为windows/shell_bind_tcp,其监听端口为4444。

1635816216694

在Web服务器上,将内网数据库服务器的4444端口,映射到Web服务器的4444端口。

1635784479986

攻击成功后,将在内网数据库服务器上建立4444端口的监听,等待连接。

1635816299400

设置msf的payload为windows/shell_reverse_tcp,其回连端口为4444,回连的ip为172.20.1.122。

1635836405546

在攻击机上用nc进行监听本地的4567端口,设置转发,将攻击机4567端口传输的数据,转发到Web服务器上。

1635837434670

1635837376773

在Web服务器上设置转发,将来自4444端口的数据,转发到本机的4444端口。

1635836343223

进行攻击。

1635837392252

反向shell连接成功。

1635837355678

https://www.cnblogs.com/wuxinmengyi/p/11598876.html

https://mp.weixin.qq.com/s/Tpapq3YQy2WaQTUT5LyMhQ

非常经典的漏洞,适合windows漏洞分析入门练习,这也是我第分析的一个Windows二进制漏洞,文中难免出现错误,希望各位前辈能够不吝赐教,多多指导。

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
prefix + '\' + path => can_path [max_buf]
prefix + '\' + path => can_path [max_buf]
Int NetpwPathCanonicalize(
    Uint16 path[ ],            // [in]    path name
    Uint8 can_path[ ],        // [out]  canonicalized path
    Uint32 maxbuf,            // [in]     max size of can_path
    Uint16 prefix[ ],        // [in]     path prefix
    Uint32* pathtype,        // [int out] path type
    Uint32 pathflags        // [in]    path flags, 0 or 1
);
Int NetpwPathCanonicalize(
    Uint16 path[ ],            // [in]    path name
    Uint8 can_path[ ],        // [out]  canonicalized path
    Uint32 maxbuf,            // [in]     max size of can_path
    Uint16 prefix[ ],        // [in]     path prefix
    Uint32* pathtype,        // [int out] path type
    Uint32 pathflags        // [in]    path flags, 0 or 1
);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!

收藏
免费 7
支持
分享
打赏 + 100.00雪花
打赏次数 1 雪花 + 100.00
 
赞赏  Editor   +100.00 2022/04/06 恭喜您获得“雪花”奖励,安全圈有你而精彩!
最新回复 (4)
雪    币: 15565
活跃值: (16922)
能力值: (RANK:730 )
在线值:
发帖
回帖
粉丝
2
什么时候上17-010啊
2022-3-6 10:30
0
雪    币: 338
活跃值: (2006)
能力值: ( LV7,RANK:110 )
在线值:
发帖
回帖
粉丝
3
有毒 什么时候上17-010啊
快了快了
2022-3-7 09:39
0
雪    币: 2216
活跃值: (2159)
能力值: ( LV2,RANK:15 )
在线值:
发帖
回帖
粉丝
4
Metasploit是个好东西。小心点用哦哈哈哈。学习了学习了。
2022-3-11 09:28
0
雪    币: 9299
活跃值: (18700)
能力值: ( LV4,RANK:40 )
在线值:
发帖
回帖
粉丝
5
多谢分享,很详细,学习了
2022-4-5 19:56
0
游客
登录 | 注册 方可回帖
返回
//