|
CVE-2017-0176原理简单分析
- 最近有朋友问到了这个漏洞的相关信息,简单分析了一下,感觉还挺有意思的,跟各位师傅分享一下自己的想法。本文不做深入分析调试,只是简单地说一下原理和漏洞触发的过程,具体的调试希望诸位能切身动手实践一下,收益颇多。
信息搜集
- 漏洞文件:gpkcsp.dll
- 漏洞函数:gpkcsp!MyCPAcquireContext()
- 漏洞参数:gpkcsp!ProvCont.key
- 数据对象:一个80字节的堆缓冲区
漏洞原理分析
背景知识
- Smart Card
- MS-RDPEFS
- MS-RDPESC
在进行后续分析之前,需要相识RDP的基础知识,否则会很困难。这部分在微软官网都有资料,我就不废话了。毕竟阅读文档也是一项技能啊,需要练。
假如RDP服务器开启了Smart Card登录功能,用户就可以利用Smart Card进行RDP登录。在向用户展示登录终端之前,服务器会利用MS-RDPEFS协议建立一个Smart Card Redirection。RDP服务器检查重定向的加密服务提供步伐(CSP)内的密钥容器的句柄,假如密钥容器的句柄不存在,则应用步伐调用MyCPAcquireContext()函数。密钥容器是包罗特定CSP的所有加密密钥的数据库。
漏洞流程:
- MyCPAcquireContext()函数首先调用SCardEstablishedContext()函数创建一个smart card上下文
- MyCPAcquireContext()函数调用ConnectToCard()函数利用上面的上下文创建一个连接句柄
- MyCPAcquireContext()函数调用SCardGetStatusChangeW()函数检查device的状态:假如card状态为SCARD_STATE_PRESENT,MyCPAcquireContext()调用DoSCardTransmit()函数发送Transmit()_Call消息进行smart card读取,包罗对应的smart card device上的序列号和不同的文件
- 调用gpkcsp!VerifyDivPIN+0x247()函数读取安全域类型文件。gpkcsp!VerifyDivPIN+0x247()函数首先选择Master File(MF)然后发送一个SELECT命令,在DataField字段中,包罗安全域文件名称((\xa0\x00\x00\x00\x18\x0f\x00\x01\x63\x00\x01)。假如文件存在,smart card响应“\x61\xff”状态,server发送GET RESPONSE命令去读取文件。假如文件不存在,server再次发送一个SELECT命令,但是为不同的文件名称("\x47\x54\x4f\x4b\x18")。假如文件存在,然后函数发送GET RESPONSE命令,LeField字段的值为0xff。此时,smart card通过Transmit_Return消息返回文件的内容。
- Transmit_Return消息长度存在cbRecvLength字段,并且真实数据存储在pbRecvBuffer字段。MyCPAcquireContext()函数从cbRecvLength中减去7,并从ProvCont.key变量中的pbRecvBuffer中存储(cbRecvLength -7)个字节。其中,ProvCont的结构如下:
struct ProvCont{ int va1_00; HANDLE handle_04; int var2_08, var2_0C, var3_10, var5_14; char key[0x80]; int var6_98; HCRYPTKEY h11; HCRYPTKEY hc2; ... }其中ProvCont.key的长度是0x80,但是在存储pbRecvBuffer之前函数不检查(cbRecvLength -7)是否小于0x80。假如攻击者可以模拟smart card device并在pbRecvBuffer中发送大于0x87的字节,则GET RESPONSE命令前面带有SELECT命令,文件名为“\xa0\x00\x00\x00\x18\x0f\x00\x01\x63\x00\x01“或”\x47\x54\x4f\x4b\x18“,然后就会发生堆缓冲区溢出环境。
综合以上分析,假如远程未经身份验证的攻击者可以通过模拟smart card device并将精心制作的smart card重定向消息发送到目标服务器来利用此漏洞将导致攻击者获得利用SYSTEM权限执行任意代码的本领。
流量检测防御思路:
<ol>检测从RDP服务器到RDP客户端的Smart Card Redirection数据包中的Transmit_Call消息,
[Client] [Server]
[Client] ----Client Name Request-----------------------> [Server]
[Client] [Server]
[Client] [Server]
[Client] |
|