010补丁对比发现的九个漏洞(4)

第三种:SMB_COM_NT_TRANS数据包的内存布局如下所述,InParameters和OutParameters之间、InData和OutData之间的缓冲区都是重叠的。

+---------------+-----------------------------------------------------------+ |  TRANSACTION  |              transaction data buffer                    | +---------------+-----------------------------------------------------------+                 | InSetup |      InParameters    |    InData      |        |                 +---------+----------------------+--------------------------+                 |        |  OutParameters  |    |        OutData          |                 +-----------------------------------------------------------+

06 当ParameterCount等于TotalParamterCount且DataCount等于TotalDataCount时,本次Transaction请求就会被服务端处理。

07 当处理transaction请求时,InParameters和InData指针有可能会被修改。

08 处理完Transaction请求后,ParameterCount和DataCount字段(通常在被调用的transaction处理函数中设置)被分别用于决定响应数据包中OutParameters和OutData缓冲区的大小。

09 SMB_COM_*_SECONDARY请求可以被用来覆盖之前SMB数据包发送的trans_parameters和trans_data的内容。无论覆盖的偏移是多少,ParameterCount和DataCount字段都会相应增加。

假设TotalParameterCount为0,TotalDataCount为16。第一个transaction请求中包含8字节的trans_data。如果第二个transaction请求中包含偏移为0的8字节数据(正常情况下偏移应该为8),就会导致第一个transaction请求的8字节数据全部被覆盖,并且接下来的8字节trans_data没有被覆盖。

[译者注]  在SMB_COM_*_SECONDARY请求中包含ParameterDisplacement和DataDisplacement两个偏移字段,用来定义当前SMB数据包中的trans_parameters和trans_data在InParameters缓冲区和InData缓冲区的偏移。正如上述举例所示,将第二个请求的DataDisplacement偏移设置为0,则第二个请求的Data内容就会覆盖第一个请求的Data内容。

10 对于复杂的transaction请求(指的是那些采用secondary才能完成传输过程的Transaction)而言,服务端根据最后一个SMB_COM_*_SECONDARY命令来确定transaction的类型。

如果最后一个命令是SMB_COM_TRANSACTION_SECONDARY,服务端后续会按照TRANS_*处理子命令;如果最后一个命令是SMB_COM_TRANSACTION2_SECONDARY,服务端后续会按照TRANS2_*处理子命令;如果最后一个命令是SMB_COM_NT_TRANSACT_SECONDARY,服务端后续会按照NT_TRANSACT_*处理子命令。

11 WriteMode字段被设置为RAW_MODE的SMB_COM_WRITE_ANDX命令,也采用Transaction方式在客户端与服务端之间进行数据交互。期间Transaction采用SMB_Parameters.FID代替SMB_Header.MID来实现前后transaction数据包的匹配。

上述关于SMB Transaction的知识已经足够了,下面赶紧开始漏洞细节吧。这些都是通过MS17-010补丁对比发现的。

Bug1:Transaction InParameters和InData缓冲区未初始化漏洞

[译者注]  通常来说,申请一块内存后的第一件事,就是将这块内存的所有字节初始化为0×00或其它内容。遗憾的是,Transaction data buffer这一点做的并不完善。

微软在SMB协议的实现上,申请Transaction data buffer后并没有将其初始化。如果我们发送多个ParameterDisplacement和DataDisplacement偏移为0的transaction请求,由于ParameterCount和DataCount字段无论偏移是多少都会相应增加(参见实现细节09),因此服务端会将未初始化的trans_parameter和trans_data缓冲区的内容作为后续处理函数的输入数据。

一般情况下,服务端进程会将输入的trans_parameter和trans_data作为不可信数据进行处理(使用前会进行验证),因此未初始化的输入通常并没有什么用处。但是,如果我们能够找到一个可以将输入数据作为输出返回给客户端的transaction命令,就可以利用这个bug来泄露输入中未初始化的数据内容。

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/2fdecb1a7e0d23e78a1017478a1e4d25.html