CVE-2017-0004相关lsass拒绝服务漏洞杂谈

昨天微软更新的补丁对lsass服务中的一处拒绝服务漏洞进行了修补,由于是远程拒绝服务漏洞遂决定看看(毕竟这种类型的这十几年也没出几个)。补丁解压之后可以发现这次更新修改了大量的dll(可以用expand.exe,原因么,用了就知道哈哈),lsass.exe本身没有修改

可能是运气好吧,我当时直接选了lsasrv这个dll,事实证明运气不错。

 

可以看到这个dll是本地密码相关的动态链接库。

通过binbiff对比可以发现确实有不少修改的地方。

因此昨天都在看这个dll的补丁对比,当时找到一些可疑的函数,其中一个函数为NegGetExpectedBufferLength,该函数是用于返回buffer长度的,补丁对比图如下。

详细的代码对比(左侧为最新的dll),可以看到红框中增加了对v8这个变量的长度校验,当获取的长度大于FFFF时,直接返回一个负值,如下所示:

 

如果此时返回的结果为90312,则会运行到后面的LsapAllocateLsaHeap。

在LsapAllocateLsaHeap中会通过之前获取的长度分配一个内存,如果前面没有检测的话,这个地方会因为超长size分配一段超大内存,导致失败,从而分配一个空指针,该空指针会被放到esi+44的地址中,从而后面导致空指针引用?这是昨天对这个地方的函数的想法,但是由于不知道怎么触发运行到这个函数(想要构造的话只能反复看该处的汇编代码,这可是个费时间的活儿),因此就暂停了分析。

 

幸运的是今天Nicolas Economou发布的一篇blog,该blog中对这次lsass服务的问题进行了精彩的阐述,并给出了相关的poc

https://www.coresecurity.com/blog/unpatched-lsass-remote-denial-service-ms16-137

该漏洞实际出现在lsasv模块的NegGetExpectedBufferLength函数中,该函数没有对发送的smb中的一个长度域做限制,当漏洞存在时,该size会作为内存分配函数LsapAllocateLsaHeap分配内存时的 size,攻击者可以将该size设置为一个大size,从而导致该处分配失败,失败后会生成一个空指针

 

该空指针会在NegpBuildMechListFromCreds中被引用,从而导致lssas进程重启。

 

运行poc之后如下,lsass崩溃。

发送的exp数据包如下,其中的f6308301即为导致漏洞触发的长度域。

可以看到漏洞触发后崩溃的地址,如kb之后发现,最后的地址即在上面NegpBuildMechListFromCreds中的RtlEnterCriticalSection之后。

直接在NegGetExpectedBufferLength下断,单步到Neg_der_read_length前如下,此时的长度变量为0。

函数运行之后可以看到此时获取的长度为f6308201,即为wireshark抓包获取的长度

最后LsapAllocateLsaHeap分配一个巨大的内存失败,返回一个空指针,并保存到esi+44的位置,该空指针会在后面被引用从而导致崩溃。

从Nicolas Economou发布的blog中可以知道实际上这个漏洞在去年的时候就补过,不过当时微软补的地方是针对NegpBuildMechListFromCreds中的空指针进行修改,而且当时补的时候对该空指针的结构也没有完全补对,直到昨天的更新中才将其中的根源NegGetExpectedBufferLength中的长度进行了限制。

时间有限,实际上我这个地方对该空指针后续的操作没有详细的调试,可能有误差,有时间后续的调试再补上吧!

 

参考

https://www.coresecurity.com/blog/unpatched-lsass-remote-denial-service-ms16-137

 

转载请注明出处

posted @ 2017-01-12 22:58  goabout2  阅读(925)  评论(0编辑  收藏  举报