IIS6 中的应用程序池身份和目录安全





5.00/5 (2投票s)
IIS6 中的应用程序池身份和目录安全
在今天的帖子中,我将介绍应用程序池和 IIS6 目录的不同安全设置。要猜到哪些权限必须设置在系统文件夹和文件上才能使应用程序正常运行,并非易事。我还会向您展示如何使用可用的跟踪选项来诊断那些恼人的安全问题。
Windows 中的每个进程,包括 *w3wp.exe*(应用程序池),都使用特定的安全标识运行。默认情况下,IIS6 使用 **NetworkService** 帐户。您可以通过其属性对话框更改特定池的此设置。IIS 中下一个可用的安全选项(**目录安全性**)配置将使用哪些凭据来访问应用程序的物理文件和文件夹。最后,您可以为 ASP.NET 应用程序定义一些自定义安全设置(包括基本/表单/Windows 身份验证、角色授权等)。在本帖中,我将主要关注前两个选项,仅在必要时提及 ASP.NET 安全。
应用程序池标识
应用程序池标识可以在其属性对话框中设置。您可以选择系统帐户之一,也可以选择自定义帐户。我们将创建一个 **testpool** 帐户并使用第二个选项。有关如何创建应用程序池帐户的详细教程可以在此处找到。对于我们的第一个练习,请按照下图所示,将密码框留空。
现在让我们创建一个将使用此应用程序池的 ASP.NET 应用程序。该应用程序将由两个文件组成。
- Default.aspx
<%@ Page Language="C#" AutoEventWireup="true" %> <%@ Import Namespace="System.Threading" %> <%@ Import Namespace="System.Security.Principal" %> <!DOCTYPE html> <html> <head> </head> <body> <%= "ASP.NET logged user: " + (User != null ? User.Identity.Name : "anonymous") %><br/> <%= "ASP.NET process identity: " + (WindowsIdentity.GetCurrent().Name) %> </body> </html>
- web.config
<?xml version="1.0"?> <configuration> <system.web> <compilation debug="true" /> <customErrors mode="Off" /> </system.web> </configuration> <configuration>
在 IIS 中创建新的 Web 应用程序(我将使用端口 8090)后,使用其中一个系统用户帐户(在我的示例中我将使用 **testdir** 用户)为其启用匿名访问。
最后,将应用程序部署到某个文件夹(我将使用 *c:\websites\sectest*),并 **仅将完全权限授予 Administrators** 组(**暂时不要管 testpool 或 testdir 帐户**)。您可以使用 `icacls` 命令检查权限。
C:\websites>icacls sectest
sectest BUILTIN\Administrators:(OI)(CI)(F)
Successfully processed 1 files; Failed processing 0 files
503 服务不可用
我们现在准备启动浏览器。
正如您所看到的,我们收到了 **503 – 服务不可用** 错误消息。我猜您已经知道问题出在哪里了,但让我们检查一下哪些日志可能提供一些关于情况的见解。**IIS 日志**(在我机器上是 *c:\WINDOWS\system32\LogFiles\W3SVC1716510118\ex120815.log*)中没有关于此错误的信息,这意味着它严重到需要记录在 **http.sys 日志** 中。快速查看 *c:\WINDOWS\system32\ogFiles\HTTPERR\httperr1.log* 证实了我们的怀疑。
2012-08-15 08:30:11 127.0.0.1 1072 127.0.0.1 8090 HTTP/1.1 GET / 503 1716510118 AppOffline TestPool
**原因短语声明:AppOffline**,这表明(根据http://support.microsoft.com/?id=820729)
发生了服务不可用错误(HTTP 错误 503)。服务不可用,因为应用程序错误导致应用程序被脱机。
我们可以在 IIS 管理器中或使用 `iisapp /a TestPool` 命令检查该池是否已脱机。那么下一个问题是:*为什么应用程序会脱机?* 答案可以在**系统事件日志**中找到。
Event Type: Error
Event Source: W3SVC
Event Category: None
Event ID: 1059
Date: 8/15/2012
Time: 11:04:20 AM
User: N/A
Computer: WIN2003SRV
Description:
A failure was encountered while launching the process serving application pool 'TestPool'.
The application pool has been disabled.
For more information, see Help and Support Center at http://go.microsoft.com/fwlink/events.asp.
紧随其后,应该有几条警告日志,内容如下:
Event Type: Warning
Event Source: W3SVC
Event Category: None
Event ID: 1021
Date: 8/15/2012
Time: 11:04:18 AM
User: N/A
Computer: WIN2003SRV
Description:
The identity of application pool, 'TestPool' is invalid.
If it remains invalid when the first request for the application pool is processed,
the application pool will be disabled. The data field contains the error number.
For more information, see Help and Support Center at http://go.microsoft.com/fwlink/events.asp.
Data:
0000: 8007052e
我们可以轻松找到,**错误 8007052e** 的描述是 **登录失败:用户名未知或密码错误**。因此,我们发现问题在于应用程序池用户的用户名或密码不正确。如果我们在系统中启用了登录失败审核,相应的日志条目也应该出现在安全事件日志中。
Event Type: Failure Audit
Event Source: Security
Event Category: Account Logon
Event ID: 680
Date: 8/16/2012
Time: 9:22:15 PM
User: NT AUTHORITY\SYSTEM
Computer: WIN2003SRV
Description:
Logon attempt by: MICROSOFT_AUTHENTICATION_PACKAGE_V1_0
Logon account: testpool
Source Workstation: WIN2003SRV
Error Code: 0xC000006A
500 服务器应用程序不可用
让我们回到浏览器窗口并按刷新。此时,我们应该会收到 **500 服务器应用程序不可用** 错误。
这次,我们在**IIS 日志**中有关于此错误的信息。
2012-08-16 19:25:53 W3SVC1716510118 127.0.0.1 GET / - 8090 - 127.0.0.1 Mozilla/4.0+
(compatible;+MSIE+8.0;+Windows+NT+5.2;+Trident/4.0;+.NET+CLR+1.1.4322;+.NET4.0C;+.NET4.0E) 500 0 0
不幸的是,除了错误号,我们没有获得太多信息。错误号 500 通常表明错误出在应用程序本身,所以让我们检查一下 ASP.NET 健康监视是否记录了什么(默认情况下,ASP.NET 配置为将任何错误消息记录到应用程序事件日志)。有两个新条目描述了应用程序为何未能启动。
Event Type: Error
Event Source: ASP.NET 4.0.30319.0
Event Category: None
Event ID: 1088
Date: 8/16/2012
Time: 9:56:31 PM
User: N/A
Computer: WIN2003SRV
Description:
Failed to execute request because the App-Domain could not be created.
Error: 0x80070005 Access is denied.
Event Type: Error
Event Source: ASP.NET 4.0.30319.0
Event Category: None
Event ID: 1325
Date: 8/16/2012
Time: 9:56:30 PM
User: N/A
Computer: WIN2003SRV
Description:
Failed to initialize the AppDomain:/LM/W3SVC/1716510118/Root
Exception: System.IO.FileLoadException
Message: Could not load file or assembly 'System.Web, Version=4.0.0.0,
Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a' or one of its dependencies.
Access is denied.
StackTrace: at System.Reflection.RuntimeAssembly._nLoad(AssemblyName fileName,
String codeBase, Evidence assemblySecurity, RuntimeAssembly locationHint,
StackCrawlMark& stackMark, Boolean throwOnFileNotFound,
Boolean forIntrospection, Boolean suppressSecurityChecks)
at System.Reflection.RuntimeAssembly.nLoad(AssemblyName fileName,
String codeBase, Evidence assemblySecurity, RuntimeAssembly locationHint,
StackCrawlMark& stackMark, Boolean throwOnFileNotFound,
Boolean forIntrospection, Boolean suppressSecurityChecks)
...
at System.Web.Hosting.ApplicationManager.CreateAppDomainWithHostingEnvironment
(String appId, IApplicationHost appHost, HostingEnvironmentParameters hostingParameters)
at System.Web.Hosting.ApplicationManager.
CreateAppDomainWithHostingEnvironmentAndReportErrors(String appId,
IApplicationHost appHost, HostingEnvironmentParameters hostingParameters)
从上面的日志中,我们可以看到在托管环境中创建 appdomain 时出现了**访问被拒绝**。由于 ASP.NET 进程以与应用程序池相同的凭据运行,我们可以猜测是 **testpool** 帐户缺少 *c:\websites\sectest* 文件夹的权限。让我们为 **testpool** 帐户添加**读取权限**。
C:\websites>icacls sectest
sectest BUILTIN\Administrators:(OI)(CI)(F)
WIN2003SRV\testpool:(OI)(CI)(R)
Successfully processed 1 files; Failed processing 0 files
然后再次重新加载浏览器。
目录安全性
401.5 拒绝访问
您应该会收到一个略有不同的**拒绝访问**错误。在 IIS 日志中,我们可以检查到其代码是 401.5。
2012-08-16 22:32:26 W3SVC1716510118 127.0.0.1 GET / - 8090 - 127.0.0.1 Mozilla/4.0+
(compatible;+MSIE+8.0;+Windows+NT+5.2;+Trident/4.0;+.NET+CLR+1.1.4322;+.NET4.0C;+.NET4.0E) 401 5 0
子代码非常重要,它通知我们*由 ISAPI/CGI 应用程序进行的授权失败*(根据http://blog.crowe.co.nz/archive/2006/06/15/231.aspx)。在这种情况下,事件日志中没有信息,因此我们需要尝试更详细的方法。这时,Windows 事件跟踪就派上用场了。我们将使用通用的 **“IIS: WWW Server”提供程序**(更多关于提供程序和 IIS6 跟踪的信息可以在此 technet 网站上找到)。
C:\temp>logman start iistrace -p "IIS: WWW Server" 0xFFFFFFFE 0x5 -o test4.etl -
ets
Name: iistrace
Age Limit: 15
Buffer Size: 8
Buffers Written: 1
Clock Type: System
Events Lost: 0
Flush Timer: 0
Buffers Free: 2
Buffers Lost: 0
File Mode: Sequential
File Name: C:\temp\test4.etl
Logger Id: 3
Logger Thread Id: 2952
Maximum Buffers: 25
Maximum File Size: 0
Minimum Buffers: 3
Number of buffers: 3
Real Time Buffers Lost: 0
Provider Flags Level
-------------------------------------------------------------------------------
* "IIS: WWW Server" (IISAuthentication,IISSecurity,
IISFilter,IISStaticFile,IISCGI,IISCompression,IISCache,IISAll) 0x05
{3A2A4E84-4C21-4981-AE10-3FDA0D9B0F83} 0xfffffffe 0x05
The command completed successfully.
< 在上述命令完成后,请重复失败的请求,并发出 `C:\temp>logman stop iistrace -ets` 命令来停止跟踪会话。应该会创建一个新的 *trace4.etl* 文件。我们可以使用Log Parser将其转换为 .csv 文件(例如)(我们也可以使用 **tracerpt** 或任何其他可以读取 *.etl* 文件的工具)。
C:\temp>"c:\tools\logging\Log Parser 2.2\LogParser.exe" "select * from test4.etl" -o:CSV > test4.csv
生成的文件的内容如下(为简洁起见,我只复制了相关的行)。
16,IISAuthentication,AUTH_START,2012-08-16 23:02:30,
ContextId={00000000-0000-0000-0600-0060000000fb}|AuthTypeSupported=Anonymous
17,IISAuthentication,AUTH_REQUEST_AUTH_TYPE,2012-08-16 23:02:30,
ContextId={00000000-0000-0000-0600-0060000000fb}|RequestAuthType=Anonymous
18,IISAuthentication,AUTH_SUCCEEDED,2012-08-16 23:02:30,
ContextId={00000000-0000-0000-0600-0060000000fb}|AuthType=Anonymous|
NTLMUsed=0|RemoteUserName=|AuthUserName=|TokenImpersonationLevel=0x00000002
19,IISAuthentication,AUTH_END,2012-08-16 23:02:30,
ContextId={00000000-0000-0000-0600-0060000000fb}
20,IISISAPI,ISAPI_START,2012-08-16 23:02:30,ContextId={00000000-0000-0000-0600-0060000000fb}
21,IISGeneral,GENERAL_ISAPI_HANDLER,2012-08-16 23:02:30,
ContextId={00000000-0000-0000-0600-0060000000fb}
22,IISCache,URL_CACHE_ACCESS_START,2012-08-16 23:02:30,
ContextId={00000000-0000-0000-0600-0060000000fb}|RequestURL=/
23,IISGeneral,GENERAL_GET_URL_METADATA,2012-08-16 23:02:30,
ContextId={00000000-0000-0000-0600-0060000000fb}|
PhysicalPath=C:\websites\sectest\|AccessPerms=Read+Exec+Script
24,IISCache,URL_CACHE_ACCESS_END,2012-08-16 23:02:30,
ContextId={00000000-0000-0000-0600-0060000000fb}|PhysicalPath=
C:\websites\sectest\|URLInfoFromCache=0|URLInfoAddedToCache=0|ErrorCode=0x00000000
25,IISCache,HTTPSYS_CACHEABLE,2012-08-16 23:02:30,ContextId=
{00000000-0000-0000-0600-0060000000fb}|HttpsysCacheable=0|Reason=URL_CHANGE_BY_FILTER
26,IISISAPI,ISAPI_END,2012-08-16 23:02:30,ContextId={00000000-0000-0000-0600-0060000000fb}
27,IISFilter,FILTER_START,2012-08-16 23:02:30,
ContextId={00000000-0000-0000-0600-0060000000fb}|
FilterName=c:\WINDOWS\Microsoft.NET\Framework\v4.0.30319\\aspnet_filter.dll
28,IISFilter,FILTER_LOG_START,2012-08-16 23:02:30,
ContextId={00000000-0000-0000-0600-0060000000fb}|OrigClientHostName=127.0.0.1|
OrigClientUserName=|OrigServerName=127.0.0.1|OrigOperation=GET|
OrigTarget=/eurl.axd/8b86b9faa4046348912ac0adbc7fb2c7/|
OrigParameters=|OrigHttpStatus=401|OrigWin32Status=0
29,IISFilter,FILTER_LOG_END,2012-08-16 23:02:30,
ContextId={00000000-0000-0000-0600-0060000000fb}|FinalClientHostName=127.0.0.1|
FinalClientUserName=|FinalServerName=127.0.0.1|FinalOperation=GET|FinalTarget=/|
FinalParameters=|FinalHttpStatus=401|FinalWin32Status=0
30,IISFilter,FILTER_END,2012-08-16 23:02:30,ContextId={00000000-0000-0000-0600-0060000000fb}
31,IISGeneral,GENERAL_REQUEST_END,2012-08-16 23:02:30,
ContextId={00000000-0000-0000-0600-0060000000fb}|BytesSent=2032|
BytesReceived=249|HttpStatus=401|HttpSubStatus=5
`AUTH_SUCCEEDED` 事件通知我们 IIS(以及 ASP.NET)正在使用匿名帐户(我们在应用程序的*目录安全性*选项卡中配置的帐户)访问文件,并且从最后的 `GENERAL_REQUEST_END` 中,我们可以读到它并未成功。
200 OK
那么,让我们授予 **testdir 帐户读取权限**。
C:\websites>icacls sectest
sectest BUILTIN\Administrators:(OI)(CI)(F)
WIN2003SRV\testdir:(OI)(CI)(R)
WIN2003SRV\testpool:(OI)(CI)(R)
Successfully processed 1 files; Failed processing 0 files
并最后一次重新加载浏览器::)
我希望您能从本文提供的信息中受益于您在 IIS 安全方面的斗争。在接下来的帖子中,我计划深入探讨 WCF 激活过程和 IIS7 的跟踪选项,敬请关注。 :) 如果您有任何问题或对今天帖子中介绍的跟踪问题有更好的想法,请给我发消息或留下评论。
分类于:CodeProject,诊断 IIS