问题现象

ASP.NET应用程序security token相关的句柄泄露一般都与impersonate机制相关。通常发生了这种问题会导致整个操作系统性能减慢,在系统日志中有可能记录2020错误。

Event Type: Error
Event Source: Srv
Event Category: None
Event ID: 2020
Date: 12/24/2008
Time: 12:13:31 AM
User: N/A
Computer: MYW2K3
Description:
The server was unable to allocate from the system paged pool because the pool was empty.

如果在这种情况下抓系统kernel dump,查看dump中paged pool,可以发现大部分都被token占用。从进程管理器我们也可以看到w3wp.exe和lsass.exe的handle数量远大于其他进程,并且持续增长。

0: kd> !token ea698028
_TOKEN ea698028
TS Session ID: 0
User: S-1-5-21-606747145-527237240-1605580848-740255

如何在不同版本的操作系统中抓取kernel dump,可以参考如下文章。

How To Enable Windows XP to Capture a Complete or Kernel Memory Dump
How to generate a kernel dump file or a complete memory dump file in Windows Server 2003
How to generate a kernel or a complete memory dump file in Windows Server 2008 and Windows Server 2008 R2

另外关于paged/nonpaged pool, 可以参考Mark Russinovich的博客文章

Pushing the Limits of Windows: Paged and Nonpaged Pool

问题调试

在没有源代码的情况下如何找到什么地方调用了impersonate相关的方法呢?我们可以尝试以下两种方式。

1. 在应用程序dump文件中直接搜索该方法调用。 要实现impersonate就必须要调用相关的Windows APIs:LogonUserDuplicateToken,我们可以在内存中搜索哪些assembly引用了这些API,然后通过ILSpy之类的IL反汇编工具来查看相应的代码。

0:018> s-a 0 L?7fffffff "LogonUserA" 
0e752a90  4c 6f 67 6f 6e 55 73 65-72 41 00 44 75 70 6c 69  LogonUserA.Dupli 
0e762a90  4c 6f 67 6f 6e 55 73 65-72 41 00 44 75 70 6c 69  LogonUserA.Dupli 
77f747e4  4c 6f 67 6f 6e 55 73 65-72 41 00 4c 6f 67 6f 6e  LogonUserA.Logon 

0:018> !address 0e752a90  
0e750000 : 0e752000 - 00002000 
                    Type     01000000 MEM_IMAGE 
                    Protect  00000020 PAGE_EXECUTE_READ 
                    State    00001000 MEM_COMMIT 
                    Usage    RegionUsageImage 
FullPath C:\WINNT\Microsoft.NET\Framework\v2.0.50727\Temporary ASP.NET Files\securityhandleleak\91744b5d\ab584e94\App_Web_oeootcha.dll

如果该命令返回记录比较多,我们可以通过以下命令来查看

0:000> .foreach (place { s-[1]a 0 L?7fffffff "LogonUser" }) {!address place} 
    03530000 : 03532000 - 0000e000 
                    Type     01000000 MEM_IMAGE 
                    Protect  00000020 PAGE_EXECUTE_READ 
                    State    00001000 MEM_COMMIT 
                    Usage    RegionUsageImage 
                    FullPath C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\Temporary ASP.NET Files\erpapv\be46890c\b4f7eeae\assembly\dl3\83aa2552\f8a67fd5_af8fc901\Assembly1.DLL
 
    03590000 : 03592000 - 0000e000 
                    Type     01000000 MEM_IMAGE 
                    Protect  00000020 PAGE_EXECUTE_READ 
                    State    00001000 MEM_COMMIT 
                    Usage    RegionUsageIsVAD 
    035b0000 : 035b2000 - 00011000 
                    Type     01000000 MEM_IMAGE 
                    Protect  00000020 PAGE_EXECUTE_READ 
                    State    00001000 MEM_COMMIT 
                    Usage    RegionUsageImage 
                    FullPath C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\Temporary ASP.NET Files\erpapv\be46890c\b4f7eeae\assembly\dl3\73e6c81e\fcbd4e76_6f96c901\Approve.DLL
 
    03700000 : 03702000 - 00032000 
                    Type     01000000 MEM_IMAGE 
                    Protect  00000020 PAGE_EXECUTE_READ 
                    State    00001000 MEM_COMMIT
                    Usage    RegionUsageImage 
                    FullPath C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\Temporary ASP.NET Files\erpapv\be46890c\b4f7eeae\assembly\dl3\19c4bca1\9a54ebdc_5a97c901\Assembly2.DLL
 
……………

2. 第二种方法是通过调试器在程序运行过程中记录相应API调用栈。

  • 安装调试工具Debug Tool for Windows 将以下配置文件存为TokenLeak.cfg,将OutputDir中目录更改为你需要存log的目录。
  • 打开命令行,转到调试器安装目录,运行以下命令
  • Cscript.exe –p <PID of the w3wp.exe has token leak problem> -c <FullPathTo TokenLeak.cfg>
  • 监测w3wp.exe handle数量增长情况并查看生成的日志文件,日志文件中记录了调用相应API调用栈,根据这些调用栈我们可以回头查看源代码来将没有关闭的handle释放掉。
# ChildEBP RetAddr  Args to Child
00 01f1ef08 0e49126a 01f1f128 01f1f028 01f1ef28 ADVAPI32!LogonUserA (FPO: [Non-Fpo]) (CONV: stdcall) 
01 01f1f244 0e790605 00000001 00000000 060e3178 CLRStub[StubLinkStub]@e49126a 
02 01f1f2a4 0e790505 00000000 00000000 00000000 App_Web_oeootcha!_Default.impersonateValidUser(System.String, System.String, System.String)+0x7d*** WARNING: Unable to verify checksum for C:\WINNT\Microsoft.NET\Framework\v2.0.50727\Temporary ASP.NET Files\securityhandleleak\91744b5d\ab584e94\App_Web_oeootcha.dll  (Managed) 
03 00000000 66f12980 00000000 00000000 00000000 App_Web_oeootcha!_Default.Page_Load(System.Object, System.EventArgs)+0x3d (Managed) 
04 01f1f504 6628efd2 00000000 00000000 00000000 
Configuration File:
 
<ADPlus> 
      <Settings> 
                      <RunMode> CRASH </RunMode> 
                      <Sympath> http://msdl.microsoft.com/download/symbols </Sympath> 
                      <Option> Quiet </Option> 
                      <OutputDir> d:\HandleLeak </OutputDir> 
      </Settings> 
      <Breakpoints> 
                      <NewBP> 
                                      <Address> advapi32!LogonUserA </Address> 
                                      <Type> BP </Type> 
                                      <Actions> stack  </Actions> 
                                      <CustomActions>  </CustomActions> 
                                      <ReturnAction> G </ReturnAction> 
                      </NewBP>   
                      <NewBP>
 
                                      <Address> advapi32!LogonUserW </Address> 
                                      <Type> BP </Type> 
                                      <Actions> stack  </Actions> 
                                      <CustomActions>  </CustomActions> 
                                      <ReturnAction> G </ReturnAction> 
                        </NewBP>  
      </Breakpoints> 
</ADPlus>

 

希望以上内容对你有所帮助

 

weizhao

posted on 2013-04-10 13:47  微软互联网开发支持  阅读(1253)  评论(0编辑  收藏  举报