MS09-026漏洞分析:开发者如何检测RPC接口风险

本文详细解析MS09-026安全更新中涉及的RPC NDR20编组引擎漏洞,指导开发者通过检查IDL生成的存根代码中的FC_SMVARRAY/FC_LGVARRAY等特定模式来识别受影响接口,并提供具体检测步骤和代码示例。

MS09-026:开发者如何判断其RPC接口是否受影响

今日我们发布了MS09-026,修复了Microsoft Windows RPC(远程过程调用)NDR20编组引擎中的一个漏洞。该组件负责准备通过网络发送的数据,并将其转换回服务器或客户端应用程序使用的格式。NDR20专用于使用RPC传输数据的32位应用程序,而RPC的NDR64编组引擎用于64位应用程序。

此NDR20中的错误仅影响在定义其用于通信的RPC接口时使用特定结构风格的应用程序。这种特定结构风格是非一致可变数组(non-conformant varying array)。更多信息可在http://msdn.microsoft.com/en-us/library/aa373542(VS.85).aspx找到。请注意,这种结构风格并不常见,任何受支持版本的Windows附带的RPC接口均未使用它。然而,我们仍然提供了修复,因为这是一种受支持的结构风格,可能在某些地方使用。

那么,开发者如何知道RPC接口是否受影响?公告的FAQ中说明了以下内容。

哪些RPC应用程序可能受此漏洞影响? 要检测应用程序是否受此问题影响,用户必须有权访问用于编译客户端或服务器应用程序的IDL文件。如果生成的存根包含FC_SMVARRAY或FC_LGVARRAY,后跟FC_VARIABLE_REPEAT和FC_VARIABLE_OFFSET,则RPC应用程序可能易受此问题影响。

这些代码定义(FC_SMVARRAY、FC_LGVARRAY、FC_VARIABLE_REPEAT和FC_VARIABLE_OFFSET)用于在编译时由midl.exe编译RPC接口的IDL文件时生成的RPC客户端和服务器存根中,特别是在使用/Oicf开关时(http://msdn.microsoft.com/en-us/library/aa367352(VS.85).aspx)。还存在其他开关(在前述链接中定义),这些开关将生成不同格式的存根,因此如有疑问,请确保使用/Oicf开关。

利用公告所述内容,开发者可以通过以下步骤检查从IDL生成的*_c.c或*_s.c存根:

  1. 找到存根文件中包含的MIDL_TYPE_FORMAT_STRING。
  2. 扫描定义,查找行注释中的FC_SMVARRAY或FC_LGVARRAY。
  3. 继续向下扫描,查找FC_VARIABLE_REPEAT后跟FC_VARIABLE_OFFSET。
  4. 如果在遇到FC_END定义之前找到这两个定义,则接口受影响。
  5. 如果遇到FC_END定义,则该数组类型是安全的,因此重复步骤2到4直到MIDL_TYPE_FORMAT_STRING的末尾。

以下是一个受此问题影响的示例MIDL_TYPE_FORMAT_STRING:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
static const repro_MIDL_TYPE_FORMAT_STRING repro__MIDL_TypeFormatString =
{
 0,
 {
  NdrFcShort( 0x0 ), /* 0 */
/*  2 */
  0x12, 0x8, /* FC_UP [simple_pointer] */
/*  4 */ 0x8, /* FC_LONG */
  0x5c,  /* FC_PAD */
/*  6 */
  0x16,  /* FC_PSTRUCT */

  0x1f,  /* FC_SMVARRAY */
  0x3,   /* 3 */
/* 40 */  NdrFcShort( 0x3c ), /* 60 */
/* 42 */  NdrFcShort( 0x5 ),  /* 5 */
/* 44 */  NdrFcShort( 0xc ),  /* 12 */
/* 46 */  0x28,               /* Corr desc:  parameter, FC_LONG */
  0x0,          /*  */
/* 48 */  NdrFcShort( 0x0 ),  /* x86 Stack size/offset = 0 */
/* 50 */  NdrFcShort( 0x1 ),  /* Corr flags:  early, */
/* 52 */
  0x4b,         /* FC_PP */
  0x5c,         /* FC_PAD */
/* 54 */
  0x48,         /* FC_VARIABLE_REPEAT */
  0x4a,         /* FC_VARIABLE_OFFSET */
/* 56 */  NdrFcShort( 0xc ),  /* 12 */
/* 58 */  NdrFcShort( 0x0 ),  /* 0 */

/* 74 */  0x12, 0x10,          /* FC_UP [pointer_deref] */
/* 76 */  NdrFcShort( 0xffb6 ),     /* Offset= -74 (2) */
/* 78 */
  0x5b,          /* FC_END */

此外,开发者可以直接检查其IDL,并了解其接口是否受影响。对于受影响的接口,将存在如下定义,其中传递了非固定大小结构的数组(如下方蓝色所示)。注意,绿色数组是一个可变数组(http://msdn.microsoft.com/en-us/library/aa379375(VS.85).aspx),因为它具有固定大小但包含可变数量的元素。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
interface foo
{
                typedef struct
                {
                                int a;
                                int **pp;
                                char *buf;
                }  test;

                void bar([in] int count,
                               [out, length_is(count)] test r[7]);
}

具有受影响RPC接口的开发者应强烈建议其客户安装此补丁,特别是如果RPC接口是匿名的。

  • Nick Finco and Bruce Dang, MSRC Engineering
comments powered by Disqus
使用 Hugo 构建
主题 StackJimmy 设计