Доступ к разделу реестра "..." запрещен для олицетворенного администратора - PullRequest
2 голосов
/ 07 апреля 2011

Вот сценарий:
1. Приложение уже работает как локальный администратор
2. Оно подражает учетной записи домена, которая также является администратором в локальном окне
3. В то время как олицетворяетприложение пытается создать ключ для ключа, который имеет полный доступ к группе администраторов для «Этот ключ и подразделы».

Этот шаг завершается с ошибкой UnauthorizedException «Доступ к разделу реестра ..» запрещен.Теперь, если я явно ACL regkey для пользователя домена, создание regkey проходит.Но тогда это решение противоречит цели нахождения в группе администраторов.

Есть идеи, что здесь может пойти не так?

РЕДАКТИРОВАТЬ : я работаю на Windows Server 2008R2.Я понял, что эта проблема связана с включенным UACМетод LogonUser возвращает ограниченный токен, у которого нет повышенных прав доступа к реестру.Любые идеи о том, как получить повышенный доступ с помощью метода LogonUser?

Вот как я это называю:
IntPtr token = IntPtr.Zero;<br> LogonUser(username, domain, password, LOGON32_LOGON_BATCH, LOGON32_PROVIDER_DEFAULT, out token)

1 Ответ

3 голосов
/ 03 марта 2012

Я предложу несколько вещей для проверки:

  • Вы должны указать свой класс (который выполняет олицетворение) для запроса режима полного доверия, который вы можете сделать, используя

    [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);
        }
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...