作者:Nazim Lala
介绍
访问控制列表 (ACL) 是与对象关联的权限列表。 其中每个权限条目称为访问控制项 (ACE);ACE 包含与特定标识的特定对象关联的权限。 例如,针对文件系统对象,可以对 NTFS 上的文件/目录设置 ACL。
可以使用图形用户界面 (GUI) 工具(如“我的电脑”或“Windows® 资源管理器”)设置或编辑 ACL。 只需右键单击其中一个工具中的任意文件或文件夹资源,选择“属性”,然后单击“安全”选项卡,即可查看所选资源上 ACL 的图形表示形式。 在此对话框中,可以对文件和文件夹等系统资源应用或移除组或用户权限。 还可以使用命令行实用工具 Cacl.exe 来显示或修改文件 ACL。
ACL 基本知识
从一些 ACL 基本知识开始是很有用的。
常见 IIS 权限
ACE 中最常见的权限是读取、写入、执行和列出文件夹内容。
- 读取 / 写入权限。 读取和写入权限分别授予对文件系统对象的读写权限。
- 列出文件夹内容权限。 列表文件夹内容权限用于显示文件夹的内容,并且需要在目录上注册文件更改通知。
- Execute 权限。 执行权限用于指定操作系统是否应作为指定用户执行特定应用程序。 这不包括动态应用程序方案,如 PHP(或 Microsoft® ASP.NET)。 调用 .php 或 .aspx 文件时正在运行代码,但不是从操作系统的透视。 应该考虑使用脚本/执行权限,而不是设置执行权限。
- 完全控制。 完全控制权限授予对文件系统对象的所有访问权限。 避免完全控制,并使用更精细的读取/写入权限。
- IIS 脚本/执行权限。 具有动态内容的文件,如 .php(或 .aspx)文件,需要脚本权限才能运行。 但请注意,虽然文件系统 ACL 有执行标志,但它们没有脚本。 这是因为 Internet Information Services 7 及以上版本(IIS 7 及以上)具有特殊配置来表示特定文件是否具有动态内容;此配置存储在文件系统 ACL 之外的 IIS 配置中。 讨论脚本或执行权限时,其实际上是 IIS 配置,而非文件系统执行权限。
- 对象继承。 文件系统 ACL 通常是继承的。 在某些情况下,父目录可能具有非常松散的 ACL,需要在子级替代这些 ACL 才能充分锁定内容。 在托管方案中,这不太可能是问题,因为根目录中几乎没有权限。
常见 IIS 标识
可以通过 ACL 允许或拒绝对特定标识的权限,以保护内容。 有两种类型的标识:进程标识(IIS 工作进程启动时使用的标识)和请求处理程序标识(来自请求身份验证的标识)。
- 工作进程标识 (WPI)。 IIS 工作进程作为 WPI 运行,可以通过 IIS 中的应用程序池配置设置进行配置。 Windows Server® 2003 上的 IIS 6.0 和 Windows Server® 2008 上的 IIS 7 及更高版本将“网络服务”标识作为默认 WPI。 但是,Windows Server® 2008 R2 使用应用程序池标识作为默认 WPI。 如果应用程序进行验证和模拟,那么请求处理程序标识就是已验证用户标识。
如果 Php.ini 将 fcgi.impersonate 设置为“true”(建议用于 IIS),那么 PHP 进程将作为已验证的用户运行。 需要注意的是,在匿名身份验证的情况下,已验证的用户会是配置的匿名用户。 - IIS_IUSRS。 这是内置的标识组,是服务器上所有工作进程标识 (WPI) 的容器。 IIS 自动包括此组中的所有 WPI(无需手动添加)。
在 Windows Server 2003 上的 IIS 6.0 上,此组称为 IIS_WPG。 这是包含所有 WPI 的总体组,因此不是隔离内容的良好候选者。 在任何应用程序池中运行的任何应用程序都将作为属于该组的标识运行,因此赋予此组读取访问标识所有应用程序都能够读取内容。 - IUSR / 匿名用户标识。 内置 IUSR 帐户是默认的,用于表示使用匿名身份验证的任何人的用户标识。 匿名用户标识是可配置的,并且可以设置为除此内置默认标识之外的标识。
在实践中,应该为匿名用户帐户配置自定义帐户,并且从不使用内置帐户。 理解在 IIS 中,匿名用户并不是缺少已验证用户非常重要。 相反,匿名请求应被视为已验证用户是匿名用户标识的请求。 - 应用程序池标识。 这是与特定应用程序池相关联的虚拟标识。 每当用户创建应用程序池时,都会随它创建虚拟标识(安全标识符或 SID);将此标识注入 IIS 工作进程,以便在此应用程序池下运行的工作进程可以访问锁定到此虚拟标识的权限的内容。 在 Windows Server 2008 Service Pack 2 (SP2) 中,管理员可以使用此虚拟标识创建其工作进程。 这在 IIS 应用程序池配置设置中可配置为“应用程序池标识”类型,并且是 Windows Server 2008 R2 的默认 WPI 标识类型。 (标识对于创建它的应用程序池是唯一的,因此可以用于更有效地将服务器上的内容隔离到应用程序池。)
- 已验证用户标识。 如果应用程序使用任何形式的身份验证(包括匿名身份验证),那么这就是已验证用户的标识。 在匿名身份验证的情况下,此标识将是已配置的匿名用户标识。
IIS 执行管道
要了解哪些标识适用于哪些阶段,了解 IIS 执行管道的基本知识是很有帮助的。 管道中最适用的两个部分是身份验证和处理程序映射。
身份验证。 在进行身份验证之前,已验证用户上下文是未知的,并且所有 IIS 工作进程都作为 WPI 运行。 如有 PHP 请求,它试图在请求经过验证之前访问内容,那么 WPI 需要访问该内容。 当使用在 IIS 管道的全局预开始请求阶段(在身份验证之前)运行的 URL 重写程序的全局规则时,就会出现这种情况。 URL 重写程序能够根据访问的资源是文件还是目录来以不同方式处理规则。 为了对此进行评估,需要进行文件系统访问,并且由于其在执行管道中的位置,此访问请求作为 WPI 发生。
身份验证后,会设置已验证用户上下文,但在请求映射到处理程序之前,不一定要进行模拟。 对于身份验证和处理程序映射之间的阶段,最有可能以 WPI 运行。
处理程序映射。 在执行管道的这个阶段,请求会映射到处理程序;例如,对 *.php 的请求会映射到 FastCGI 处理程序。 发生此映射并启用模拟后,处理程序标识为“已验证用户”,并且此阶段中的所有资源访问都使用已验证用户标识进行。
选择标识
确定授予权限的正确帐户取决于应用程序的配置文件和关键资源。 主要注意事项是授予哪些权限以及你是否经过验证。
- 授予适当权限。 动态内容,如 PHP 和 ASP.NET 应用程序需要 IIS 脚本权限和读取访问。 如果需要运行可执行文件,它们需要具有 IIS 执行权限,并且需要在 CGI 限制列表中正确配置。 任何未由用户上传的内容只需要对文件系统进行读取访问。
将由用户上传的内容应位于分配写权限的单独文件夹中。 重要的是不要授予此文件夹 IIS 执行或脚本权限,这样用户就不能上传和执行恶意代码。
一般来说,WPI 应该具有对所有内容的读取访问,以便应用程序正常工作。 - 需要身份验证的应用程序。 对于需要身份验证的应用程序,将所有资源锁定到包含所有已验证用户的组中。 如果有不同类别的用户(管理员和非管理员),请创建单独组,并相应地授予访问权限。 例如,如果应用程序有包含管理脚本的管理目录,请仅将读取此目录的权限授予管理组。 如果应用程序正在模拟,那么处理程序标识就是已验证用户;否则,它就是 WPI。 如果在 Php.ini 文件中将 fcgi.impersonate 设置为“true”,那么 fcgi 进程标识就是已验证用户标识;否则,它就是 WPI。 有了这些信息,管理员可以确定要放置在内容上的正确 ACL 集。
- 匿名运行的应用程序。 需要注意的是,在 IIS 上匿名运行表示是以匿名用户表示进行验证。 在这种情况下,请将资源锁定到应用程序池标识或自定义配置的匿名标识,并通过匿名标识授予对应用程序池标识的访问权限。 如果授予 IIS_IUSRS 组对内容的访问权限,则任何应用程序池中运行的应用程序都可以访问内容。 如果允许匿名用户上传文件,应用程序应确保对这些用户可以上传的内容类型进行进一步检查,以确保服务器的安全。
如何设置 ACL
有几种方法可以通过 shell 设置 ACL,包括 Icacls.exe 等命令行工具。 本文重点介绍可用于设置 ACL 的 Web 部署工具清单 (XML) 机制。 当通过 Web 部署工具安装应用程序时,将使用此方法。
要授予用户 Foo 对 MyApp 文件系统目录的读取、执行和写入权限,请在 Manifest.xml 文件中添加以下行:
<setAcl path="MyApp" setAclAccess="ReadAndExecute, Write" setAclUser="Foo" />
若要针对 MyApp/Upload 路径设置 ACL 以允许匿名用户上传内容,请将以下命令行添加到 Manifest.xml 文件中:
<setAcl path="MyApp/Upload" setAclAccess="Write" setAclUser="anonymousAuthenticationUser" />
请注意,anonymousAuthenticationUser 是特殊令牌,将解析为配置的匿名身份验证标识。
若要授予应用程序池标识对 MyApp\Data 文件夹的读取权限,请将以下命令行添加到 Manifest.xml 文件中:
<setAcl path="MyApp/Data" setAclAccess="Read" />
请注意,此处未使用 setAclUse r(其默认值为“应用程序池标识”)。