BlockingSessionSetupAndX函数用于处理上述两种格式的SMB_COM_SESSION_SETUP_ANDX请求,其伪代码如下所述:
BlockingSessionSetupAndX() { // ... // check word count if (! (request->WordCount == 13 || (request->WordCount == 12 && (request->Capablilities & CAP_EXTENDED_SECURITY))) ) { // error and return } // ... if ((request->Capablilities & CAP_EXTENDED_SECURITY) && (smbHeader->Flags2 & FLAGS2_EXTENDED_SECURITY)) { // this request is Extend Security request GetExtendSecurityParameters(); // extract parameters and data to variables SrvValidateSecurityBuffer(); // do authentication } else { // this request is NT Security request GetNtSecurityParameters(); // extract parameters and data to variables SrvValidateUser(); // do authentication } // ... }由上可知,如果发送Extended Security的SMB_COM_SESSION_SETUP_ANDX请求(WordCount为12)。数据包中含有CAP_EXTENDED_SECURITY,但没有FLAGS2_EXTENDED_SECURITY。服务端会将其当作NT Security请求来处理(WordCount为13)。
我们也能修改请求数据包,使服务端将其当作包含CAP_EXTENDED_SECURITY和FLAGS2_EXTENDED_SECURITY的NT Security请求(WordCount为13)。
但后一种情况没有什么用处,因为在GetExtendSecurityParameters函数中针对ByteCount数值又做了额外的检查。
通常,服务端会在调用不同命令的处理函数之前,通过SrvValidateSmb函数验证WordCount和ByteCount字段的合法性。WordCount*2和ByteCount不能超过实际接收的data大小。
利用上述混淆漏洞(将WordCount为12的Extended Security请求,当作WordCount为13的NT Security请求来处理),当服务端从数据包中提取parameters和data时,可以实现从错误的位置读取ByteCount的数值。
由于ByteCount数值只是用来计算缓冲区的大小,以便存储NativeOS和NativeLanMan的unicode字符串(UTF16),因此这个bug并不会引起任何内存崩溃或信息泄露。NativeOS和NativeLanMan的大小根据“ByteCount – other_data_size”计算,并且它们使用的缓冲区从分页内存池中申请。
NSA武器库中的Eternalchampion利用这个漏洞,将UNICODE_STRING.MaximumLength设置为0x15ff,并将shellcode载荷存放在这个缓冲区中。由于非分页内存池在win8之前系统是可以被执行的,因此只要后续能调用该缓冲区(利用上面的越界写漏洞),就能实现shellcode载荷的执行。
NSA武器库中的Eternalblue也利用这个bug来创建了一个缓冲区,我们能够控制合适申请或释放该缓冲区。
备注:当NTLM身份认证被禁止时,就无法利用该bug了。