- A+
服务器操作系统:Windows Server 2003 SP2、2008 SP2、2008 R2 SP1、2012到2012 R2
微软平板:Windows RT和Windows RT 8.1。
黑客可以构造特定的数据包在Schannel中远程执行恶意代码,并藉此漏洞入侵系统。因为Schannel是Windows实现SSL/TLS协议的组件之一,所以CVE-2014-6321漏洞就像是OpenSSL中的Heartbleed漏洞,危害巨大。
思科Talos团队表示,MS14-066涉及一个常见漏洞揭露CVE-2014-6321。虽然该漏洞是单一的CVE,但是实际上却包含了多个漏洞,范围广从缓冲区到凭证验证。
Rapid7资深信息安全工程经理RossBarrett表示,目前CVE-2014-6321漏洞的影响还不大,但是如果攻击代码泄漏,该漏洞将会成为严重的问题,且影响会扩大。
目前,微软也尚未接到有关该漏洞已公开用来攻击用户的消息,而微软在官网也表示,此安全更新可以更正Schannel清理特定封包的方式,进而消除此项安全风险。
网上关于CVE-2014-6321漏洞的详情与利用方法鲜有披露。我们通过新发布的补丁来一探究竟。
通过对打补丁前后的schannle.dll文件进行二进制比较,可查看到一些修改过的函数,其中几个是类DTLSCookieManager的方法。由此表明了至少有一个bug位于DTLSCookieManager类中。而大家最关心的bug好像是位于schannel!DecodeSigAndReverse(…)中,DecodeSigAndReverse函数的变更如下所示。
由从上图可清楚的看到DecodeSigAndReverse函数中间添加了一些新的代码块
上图可看到新添代码块把运行路径指向了memcpy调用(实际上是两次memecpy函数调用)。程序是如何运行到这部分代码?可查看DecodeSigAndReverse函数在未打补丁版本中的调用路径。
根据调用路径中涉及的函数名称,Schannel可能是在处理一个“CertificateVerify”消息,涉及证书的认证过程(客户端发送一个证书到服务器,服务器通过证书验证客户端身份)。如果仔细查看未打补丁的函数,可从调用函数CryptDecodeObject的参数lpszStructType发现一个关键的线索。
_In_ DWORD dwCertEncodingType, //使用的编码类型
_In_ LPCSTR lpszStructType, //结构的类型
_In_ constBYTE *pbEncoded, //指向待解码的结构
_In_ DWORD cbEncoded, //待解码结构的字节长度
_In_ DWORDdwFlags,
_Out_ void*pvStructInfo, //指向存储解码后的结构
_Inout_ DWORD *pcbStructInfo //表示解码后的据结构的字节长度
);
通过MSDN查询,我们可获知lpszStructType参数指出证书签名的结构类型。在本例中,可以是X509_ECC_SIGNATURE(ECDSA签名)和X509_DSS_SIGNATURE(DSS签名)。若选择ECC_SIGNATURE,该结构在MSDN中有具体的定义。
typedef struct _CERT_ECC_SIGNATURE {
CRYPT_UINT_BLOB r; // ECDSA签名的r值,Little-Endian字节顺序。
CRYPT_UINT_BLOB s; // ECDSA签名的s值,Little-Endian字节顺序。
} CERT_ECC_SIGNATURE, *PCERT_ECC_SIGNATURE;
其中一个memcpys函数调用的size参数好像存在问题,可能与证书的编码过程有关。
void *dest, //目的的缓冲区。
const void *src, //源的缓冲区
size_t size //字节长度。
);
据我们所知,最快速的处理方法就是在运行状态下观察这个函数(PS当然要用调试器,不然看不到哟)。因此,利用OpenSSL创建一个ECDSA签名的证书,并将IIS设置成证书认证的方式。然后,把远程调试器附加到运行IIS服务的服务器中的LSASS进程,并在比较ECC_SIGNATURE(ECDSA签名)的地方设置断点(cmpebx,2F)。
令人吃惊的是,当利用OpenSSLclient第一次尝试链接IIS服务进行认证时,断点就被触发。既然能够命中存在问题的代码,下一步就是触发漏洞。为了加快分析过程,我们决定修改OpenSSl来模糊测试这个调用路径。
在OpenSSL中,源文件s3_clnt.c实现了“clientverifymessages”的ECDSA签名。客户端的已编码的ECDSA签名由客户端上OpenSSL中ECDSA_sign(…)函数生成,最终命中IIS服务器上schannel!DecodeSigAndReverse()中的函数CryptDecodeObject(…)。如果追踪函数ssl3_send_client_verify(…),发现它最终会调用ECDSA_sign(…),下图就是对“clientverifymessages”进行ECDSA签名的代码块。
if(pkey->type == EVP_PKEY_EC)
{
if(!ECDSA_sign(pkey->save_type,
&(data[MD5_DIGEST_LENGTH]),
SHA_DIGEST_LENGTH,&(p[2]),
(unsignedint *)&j,pkey->pkey.ec))
{
SSLerr(SSL_F_SSL3_SEND_CLIENT_VERIFY,
ERR_R_ECDSA_LIB);
gotoerr;
}
s2n(j,p);
n=j+2;
}
else
#endif
为弄清楚这个调用过程,其中ECDSA_sign函数的原型如下:
int type, //可忽略
const unsigned char *dgst, //指向待签名的散列值
int dgstlen, //散列值的长度
unsigned char *sig, //指向存储DER编码的签名的存储空间
unsigned int *siglen, //签名的长度
EC_KEY *eckey //EC_KEY对象,包含了EC私钥
);
通过查阅该函数的帮助文档,可知“DER编码后的签名存储在sig中,而sig的长度存储在sig_len中”。如果打算使用OpenSSls_client向IIS发起身份认证,然后Schannel一路运行到schannel!DecodeSigAndRevers(…)函数,我们可以看到变量“p”经ECDSA_sign(…)运算的结果会提交到schannel!CryptDecodeObject(…)函数,经过解码后并传递到存在问题代码中的memcpy调用。
因此,仅需将变量“p”中的一个字节设置为一个随机值,然后不停向IIS发送“CertificateVerify”消息,直到一些奇怪的事情发生。如果等待足够的时间,可以观察由memcyp引起的进程崩溃。
进一步的分析和漏洞利用留给读者来练手。
- 我的微信
- 这是我的微信扫一扫
- 我的微信公众号
- 我的微信公众号扫一扫