对模拟的管理员拒绝访问注册表项“...”

时间:2011-04-07 01:55:12

标签: c# asp.net uac impersonation

以下是该情景:
1.该应用已作为本地管理员运行 2.它冒充域名帐户,也是本地方框的管理员 3.在模拟时,应用程序正在尝试在“管理员”组的“此键和子项”的“完全控制”键下创建一个注册表。

此步骤因UnauthorizedException而失败“访问注册表项...”被拒绝。 现在,如果我明确地为域用户ACL建立了regkey,则会创建regkey。但是,这个解决方案违背了管理组的目的。

任何想法可能会出错?

编辑:我在Windows Server 2008 R2上运行。我认为这个问题是由于启用了UAC。 LogonUser方法返回一个受限制的令牌,该令牌没有对注册表的提升访问权限。有关如何使用LogonUser方法获得提升访问权限的任何想法?

以下是我的称呼方式:
IntPtr token = IntPtr.Zero;
LogonUser(username, domain, password, LOGON32_LOGON_BATCH, LOGON32_PROVIDER_DEFAULT, out token)

1 个答案:

答案 0 :(得分:3)

我会建议几件事要检查:

  • 您应该将您的类(执行模拟)归因于完全信任模式请求,您可以使用

    [PermissionSetAttribute(SecurityAction.Demand, Name = "FullTrust")]
    
  • 此外,您应该导入“advapi32.dll”和LogonUser以供日后使用。

  • 最后,您应该获得一个安全的令牌句柄(继承自SafeHandleZeroOrMinusOneIsInvalid,它为Win32安全句柄实现提供了一个基类,其中0或-1的值表示无效句柄。)
  • 在此之内你应该像这样调用它( *使用LOGON32_LOGON_INTERACTIVE,因为BATCH不起作用*

    LogonUser(userName, domainName, password, 2, 0, out safeTokenHandle);
    

获取句柄后,您应该使用它来执行任何操作:

    WindowsIdentity impid = new WindowsIdentity(safeTokenHandle.DangerousGetHandle());

获得它后,封装你的行动:

    using (WindowsImpersonationContext imp = impid.Impersonate())
    { 
      // myActions
    }

这应该使您能够正确地执行并检测它是如何进行的。

我现在尝试在ASP.NET应用程序中执行此操作并成功完成。这是MVC应用程序控制器的工作代码:

using System;
using System.Runtime.ConstrainedExecution;
using System.Runtime.InteropServices;
using System.Security;
using System.Security.Permissions;
using System.Security.Principal;
using System.Web.Mvc;
using Microsoft.Win32;
using Microsoft.Win32.SafeHandles;

namespace StackOimpersonationExample.Controllers
{
    [PermissionSet(SecurityAction.Demand, Name = "FullTrust")]
    public class HomeController : Controller
    {
        [DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
        public static extern bool LogonUser(String lpszUsername, String lpszDomain, String lpszPassword,
                                            int dwLogonType, int dwLogonProvider, out TokenHandle phToken);

        [DllImport("kernel32.dll", CharSet = CharSet.Auto)]
        public static extern bool CloseHandle(IntPtr handle);

        public ActionResult Index()
        {
            ViewBag.Message = "This line contains status info.";


            #region ImpersonateTestUserAndWriteToRegistry

            try
            {
                const string domainName = "W8CP";
                const string userName = "testadmin";
                const string password = "sxt";

                TokenHandle tokenHandle;
                bool returnValue = LogonUser(userName, domainName, password, 2, 0, out tokenHandle);

                if (returnValue == false)
                {
                    int retVal = Marshal.GetLastWin32Error();
                    ViewBag.Message = String.Format("Failed logon: {0}", retVal);
                    throw new System.ComponentModel.Win32Exception(retVal);
                }
                using (tokenHandle)
                {
                    ViewBag.Message = "Logon successful!";
                    var newId = new WindowsIdentity(tokenHandle.DangerousGetHandle());
                    using (newId.Impersonate())
                    {
                        RegistryKey parentKey = Registry.LocalMachine;
                        RegistryKey softwareKey = parentKey.OpenSubKey("SOFTWARE", true);
                        if (softwareKey != null)
                        {
                            RegistryKey subKey = softwareKey.CreateSubKey("StackAnswer");

                            subKey.SetValue("CreatedAs", WindowsIdentity.GetCurrent().Name, RegistryValueKind.String);
                            subKey.SetValue("Website", "http://codecentral.org", RegistryValueKind.String);
                            subKey.SetValue("Email", "tonci.jukic@gmail.com", RegistryValueKind.String);

                        }
                    }
                }
            }
            catch (Exception ex)
            {
                ViewBag.Message += String.Format(" Exception: " + ex.Message);
            }
            #endregion

            return View();
        }
    }

    public sealed class TokenHandle : SafeHandleZeroOrMinusOneIsInvalid
    {
        private TokenHandle(): base(true){}

        [DllImport("kernel32.dll")]
        [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
        [SuppressUnmanagedCodeSecurity]
        [return: MarshalAs(UnmanagedType.Bool)]
        private static extern bool CloseHandle(IntPtr handle);

        protected override bool ReleaseHandle()
        {
            return CloseHandle(handle);
        }
    }
}