调试ASP.NET应用程序Security Token Handle Leak
问题现象
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: LogonUser , DuplicateToken ,我们可以在内存中搜索哪些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
分类: 技术分享 - ASP.NET
标签: handle leak , security token , impersonate , page pool , kernel dump
作者: Leo_wl
出处: http://www.cnblogs.com/Leo_wl/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
版权信息查看更多关于调试ASP.NET应用程序Security Token Handle Leak的详细内容...