Grisson's .net

源码之前,了无秘密

  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

ASP.NET工作进程的安全性身份

Security Context of ASP.NET是指ASP.NET的工作进程(Worker Process)在其他被访问的资源(例如SQL Server的服务或者网络共享文件夹)看来,是一个什么身份。

以SQL Server为例,当ASP.NET应用程序代码尝试以Windows集成登录模式(而不是用SQL Server Login ID)来连接SQL Server时,SQL Server会认为是谁在尝试连接呢?

或者,ASP.NET程序可能需要访问一个以UNC路径表示的共享文件夹 \\fileserver\share,fileserver会认为是谁在尝试文件操作呢?

 

影响Security Context的因素很多,在分析这些因素的影响之前,首先要明确两点:

(1)IIS服务本身的Service Account(默认为LocalSystem)不是一个影响因素

这是因为ASP.NET的程序并不工作在IIS的服务进程中,而是运行在一个称为“ASP.NET Worker Process”的工作进程中,这个工作进程类似一个Windows Service,但是在Windows Service列表中看不到。这个工作进程的控制程序是一个exe文件: asp_wp.exe(on Windows 2000)或者w3wp.exe(on Windows 2003)。

与此不同的是,很多其他的Service的Security Context都是Service Account,例如SQL Server的存储进程在尝试访问其他机器上的资源时,其身份就是MSSQLServer服务的启动帐号。

(2)在 Security Context这个问题上,ASP.NET Web应用程序网页和ASP.NET Web Service之间没有区别。因为两者都工作在ASP.NET Worker Process中。

 

实际影响ASP.NET Security的因素包括:

(1)ASP.NET程序所在的Windows系统(更确切地说是IIS)的版本

(2)machine.config中的processModel设置

(3)ASP.NET的Impersonation设置

(4)IIS的匿名访问用户帐号设置

(5)IIS与被访问资源(如SQL Server)是否在同一台机器上

(6)被访问的外部资源是SQL Server,还是File System(例如一个UNC共享文件夹路径)

 

Windows 2000 Server with IIS 5.0

先看Windows 2000 Server上的情况。

Machine.config的processModel

 

在\%windows%\Microsoft.NET\Framework\Version\Config目录中找到machine.config文件,其中有一个<processModel> tag:

<processModel enable="true" ... userName="machine" password="AutoGenerate" ... />

其中的userName="machine"就是指定使用本机ASPNET帐号(.\ASPNET)作为ASP.NET工作进程的默认账号。

这个默认帐号是可以修改的,如果开发人员将userName修改为一个域用户帐号:

<system.web>

   <processModel

      enable="true"

      userName="domain\user"

      password="password"

   />

</system.web>

那么ASP.NET工作进程的身份就变成了domain\user。只要这个域用户帐号拥有需要的权限,那么machine.config所在机器上所有ASP.NET程序都可以访问域中其他服务器的资源,包括存取用UNC路径指定的文件。

如果指定userName="system",那么ASP.NET程序将以LocalSystem身份运行,可以存取几乎所有本地资源,因此非常危险!

 

无论machine.config指定哪个默认帐号,这个默认帐号都可以被应用程序的web.config设置的Impersonation覆盖,即特定应用程序可以以其他身份运行。

Web.config的Impersonation

 

Web.Config中有一个<identity>元素,可以用于设置本应用程序的身份,即所谓“扮演(Impersonation)”,即应用程序扮演成IIS服务请求者或者某个固定用户的身份,访问本地或者外部资源时,资源以为是被扮演的用户在访问一样。

扮演有两种可能:

(1) 扮演IIS服务请求者,即浏览器客户端的身份

在web.config中设置:

              <identity impersonate="true" />

ASP.NET进程将扮演http/https请求者的身份。具体是什么帐号,就跟IIS的安全性设定有关了:

如果IIS允许匿名访问,那么缺省状态下,被扮演的将是Iuser_Machine帐号,即在IIS安全设置中用Enable anonymous access指定的帐号。如果修改过,那被扮演的就是修改过的帐号。

如果IIS不允许匿名访问,那么浏览器请求者的身份肯定是一个Windows帐号,这个帐号就是被扮演的对象。

(2)扮演一个固定用户

设置扮演固定用户身份,需要为<identity>元素指定userName 和password两个 attributes:

<identity impersonate="true" userName="MyServiceAccount"
                             password="Str0ng!Passw0rd"/>

显然,将password这样明码写在web.config中是不合适的。推荐的办法是使用Aspnet_setreg.exe工具,将这种信息加密后保存到注册表中。

 

无论扮演哪个帐号,微软都不推荐使用扮演,一方面是安全性问题(被扮演的帐号可能有一些程序并不需要的多余权限,可能被利用),另一方面是可伸缩性问题(Scalability),因为在访问SQL Server等资源时,无法利用连接池等手段。

资源服务器与IIS分离

以上提到的 .ASPNET,IUser_Machine都是本机帐号,即仅在IIS所在的机器上有效,如果ASP.NET代码试图访问其他机器上的资源,例如SQL Server或者UNC路径,那么资源服务器是不认的。在文件服务器看来,似乎是一个'NT AUTHORITY \ ANONYMOUS LOGON'帐号在试图访问,对于SQL Server,如果代码采用Windows集成安全模式登录,SQL Server会报错:(null)帐号登录失败。

有几种方法可以解决这个问题:

(1)放开资源服务器上的Guest帐号

(2)将IIS的匿名访问帐号改成一个domain\user

(3)在web.config设置扮演,扮演一个domain\user

第一个方法是安全性方面最忌讳的事情,所以不要这样干。后面两个方法实质一样,就是以一个资源服务器能认可的身份去访问。这种方法也有一个问题:domain user可能具备一些本来不需要的权限。更为麻烦的是,如果网管或是什么人修改了那个帐号的密码,应用程序的运行就会出问题。再有,如果想要扮演domain user,密码的保存令人头痛:不能明文放在web.config中,只好加密放在注册表中。密码加密了,加密用的key又成了烫手山芋,放在明处怕人看见,放在暗处又怕丢。

所以真正的好办法是:升级IIS所在的Windows 2000,采用Windows Server 2003!

 

Windows Server 2003 with IIS 6.0

 

再看Windows Server 2003上的情况。

Windows Server 2003将IIS的内核重写了,因此其IIS 6.0在很多方面都跟Windows 2000的IIS 5.0很不一样。从ASP.NET Security Context的角度看,最大的不同在于:

(1)ASP.NET工作进程的控制程序不同:不是aspnet_wp.exe,而是w3wp.exe。

(2)尽管在安装.NET Framework时也创建了.\ASPNET帐号,machine.config中也指定了processModel userName=”machine”,其含义却不是使用.\ASPNET帐号,而是使用NTAuthority\Network Service,作为ASP.NET工作进程的默认身份。

这个NetworkService帐号是Windows 2003引入的一个新的特殊帐号,与LocalSystem相似,这个帐号是个虚拟帐号、可以作为Service的启动帐号,但是它对本地资源的权限非常有限,因此以这个帐号为启动帐号的服务进程,对本地文件等资源几乎没有什么权限,从而Windows系统的安全性可以得到更好保证。

对ASP.NET程序来说,ASP.NET工作进程缺省以Network Service身份运行,为程序代码访问IIS之外的资源服务器提供了极大方便:

当程序代码试图访问其他机器上的资源(SQL Server或者UNC)时,其身份将不再是ANONYMOUS LOGON,而是IIS机器帐号:Domain\MachineName$。这就是所谓“代表(Delegate)”机制。NetworkService就像一个小职员,在公司内部地位很低,到了外面却代表整个公司。

因此,在Windows 2003的IIS上运行的ASP.NET 程序,如果需要访问其他机器上的SQL Server或者文件资源,只需要在资源服务器上为IIS计算机账号授权即可,既不需要修改IIS匿名访问帐号,也不需要设置扮演,省去很多麻烦。

以SQL Server为例,如果需要允许IIS上的程序登录并访问某个数据库,只需要运行如下 SQL脚本:

exec sp_grantlogin N'DomainName\IISMachineName$'

use [DatabaseName]

exec sp_grantdbaccess N'DomainName\IISMachineName$', N'IISMachineName$'

exec sp_addrolemember N'db_owner', N'IISMachineName$'

这样使用计算机账号进行资源访问,还可以得到两个好处:

(1)数据库连接可以采用Windows集成安全模式,连接字串可以光明正大地明文保存在web.config中,如:

Integrated Security=SSPI;Initial Catalog=<DatabaseName>;Data Source=<ServerName>;

(2)普通情况下,计算机账号对其他网络资源没有任何权限,因此整个系统符合Least Privilege原则,不会有什么不放心的权限。

posted on 2005-08-22 00:01  海盗  阅读(639)  评论(0)    收藏  举报