如何在不将应用程序池身份设置为本地系统的情况下从网站重新启动应用程序池?

4
我在.Net中有一个应用程序,用于为其他应用程序进行各种管理/配置。 我需要能够停止和启动应用程序池。 我已经实现了这一点,但只有在以本地系统运行应用程序池时才可以实现(这通常被认为是一个坏主意)。最初,我使用Process.Start(使用适当的ProcessStartInfo对象)启动了appcmd.exe,但这最终使我得到了一个-1073741502的退出代码,进一步的研究表明我需要使用Windows SDK进行调试,因为它与未加载程序集有关。因此,我在Microsoft.Web.Administration命名空间中找到了一个似乎更简单的解决方案:我使用以下代码,但似乎要求运行它的AppPool具有本地系统的身份(否则我会收到System.UnauthorizedAccessException)--是否有一种方法以较低的权限账户启动/停止(我更喜欢使用应用程序标识),尽管暂时提升权限也可接受。
    Dim serverManager As New ServerManager()
    Dim applicationPoolCollection As ApplicationPoolCollection = serverManager.ApplicationPools

    For Each applicationPool As ApplicationPool In applicationPoolCollection

        If applicationPool.Name = appPoolName Then
            applicationPool.Stop()
            applicationPool.Start()
        End If

    Next

我已将自定义帐户设置为标识,但我无法确定该用户的最小ACL需要什么。 作为测试,我将用户添加到本地管理员组,但仍然收到“System.UnauthorizedAccessException” - 这表明我需要为用户配置特定权限,但我不确定这是什么或如何做到这一点。 有人能帮忙吗? 问题在此处也有解释
2个回答

5
唯一的方法是,如果用于运行代码(使用Microsoft.Web.Administration)的帐户具有在IIS中执行“运行时操作”的权限,而默认情况下仅包括管理员和SYSTEM,正如您正确指出的那样,在一般情况下,公开Web上的该级别权限是不好的想法。
你应该做的是创建一个应用程序池或其他方式以高特权运行,但只能本地访问(例如使用IP和域限制),并使用额外的授权检查(例如仅允许从应用程序调用),并且受到最少的代码和最小表面所需的限制,例如仅回收属于用户的池等。这样,如果您的Web应用程序受到攻击,损坏将受到更大的限制。
现在,对于好奇的人...以下内容是“不支持”的,请不要使用,仅提供信息目的。
我们在ServerManager中使用的API来读取配置称为AHADMIN,您可以“黑入足够的读取配置”,例如如果您为ACL事物:
Cd C:\Windows\System32\inetsrv\config  
icacls . /grant yourUser:(R)  
icacls redirection.config /grant yourUser:(R)  
icacls applicationHost.config /grant yourUser:(R)  

从此时开始,您将能够使用该用户读取配置。请注意,由于加密密钥也是单独受保护的,因此此时加密属性仍然无法读取,并且您可能永远不应更改ACL,但除运行时属性(例如状态等)之外的所有内容都将可读取。绝对不要允许非特权帐户进行写访问,因为这将非常容易地允许权限提升(例如,他们可以创建一个作为SYSTEM运行并将其链接到随机目录的应用程序池,现在他们可以作为SYSTEM运行代码)。
现在,回到运行时状态,我们使用称为RSCA(运行时状态和控制API)的API,本身也受保护,只能作为SYSTEM或管理员运行,尽管您可能找到一种方法来破解它,但更改它是个坏主意。长话短说,这是不受支持的,您可能会轻易地导致系统出现问题。

谢谢,您能详细说明一下以下内容吗:您有没有任何链接/信息显示如何配置最小表面/仅本地可访问性?我可以尝试的另一个选项是使用Process.Start启动一个具有管理员凭据的应用程序来执行我想要的操作。 - Mr Shoubs
感谢您的回答,我已经添加了自己的回答,以便帮助其他人。奖励积分已发放。 - Mr Shoubs
我在这里发布了一个类似的问题(尽管我要求的答案略有不同),http://serverfault.com/questions/446764/what-permissions-does-an-application-pool-identity-required-to-manage-other-ap,所以如果你想得到额外的100分,请去看看。 - Mr Shoubs

2
使用@CarlosAg的答案,以下解决方案可行:
  1. 创建一个新用户并将其放入管理员组中

  2. 创建一个Web服务来运行重启代码,将其放置在自己的应用程序池中,作为您创建的用户运行(配置适当的应用程序池属性,例如队列长度等)

    a. 将下面的代码放入您的Web方法(或begin_reqest)中,以防止它被外部调用(我认为在IIS中还有其他方法可以做到这一点,但这是我找到的最快方法)

    b. 根据需要向Web服务代码添加其他身份验证(我们有一个可以使用的单一登录服务)。

  3. 从在ApplicationIdentity下运行的应用程序池中的网站引用此服务

这个可行。

代码:

     If Not HttpContext.Current.Request.IsLocal Then
         Const msg As String = "Only local requests are allowed"
         log4net.LogManager.GetLogger(GetType(Global_asax)).Fatal(msg)
         Throw New Exception(msg)
     End If

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接